Occurrences les plus élevées ou les plus faibles?

13

Défi:

Contributions:

  • Une chaîne contenant de l'ASCII imprimable (hors espaces, tabulations et sauts de ligne)
  • Un booléen

Production:

Les parties de la chaîne sont divisées en quatre groupes:

  • Minuscules
  • Lettres capitales
  • Chiffres
  • Autre

Sur la base du booléen, nous générons soit l'occurrence la plus élevée d'un (ou plusieurs) de ces quatre groupes, soit la plus faible, remplaçant tout le reste par des espaces.

Par exemple:

Entrée: "Just_A_Test!"
Il contient:
- 3 lettres majuscules: JAT
- 6 lettres minuscules: ustest
- 0 chiffres
- 3 autres:__!

Ce seraient les sorties pour trueou false:

true:   " ust    est "

// digits have the lowest occurrence (none), so everything is replaced with a space
false:  "            "

(Remarque: Vous êtes autorisé à ignorer les espaces de fin, les sorties peuvent donc également être " ust est"et ""respectivement.)

Règles du défi:

  • L'entrée ne sera jamais vide ou contiendra des espaces, et ne sera constituée que d'ASCII imprimables dans la plage 33-126ou à '!'travers '~'.
  • Vous êtes autorisé à prendre les entrées et / ou sorties sous forme de tableau de caractères ou de liste si vous le souhaitez.
  • Deux valeurs cohérentes et distinctes pour le booléen sont autorisées: true/ false; 1/ 0; 'H'/ 'L'; "highest"/ "lowest"; etc. Notez que ces valeurs distinctes doivent être utilisées (quelque peu) comme un booléen! Il n'est donc pas autorisé de saisir deux programmes complets, l'un qui donne le résultat correct pour trueet l'autre pour false, puis d'avoir uniquement votre code réel <run input with parameter>. Nouvelle faille par défaut pertinente que j'ai ajoutée, bien qu'elle puisse encore utiliser beaucoup de réglages finaux concernant les définitions.
  • Si l'occurrence de deux ou plusieurs groupes est la même, nous générons toutes ces occurrences.
  • Les espaces de fin nécessaires sont facultatifs, et une seule nouvelle ligne de fin est également facultative. Les espaces de tête nécessaires sont obligatoires. Et tout autre espace de tête ou nouvelle ligne n'est pas autorisé.

Règles générales:

  • C'est le , donc la réponse la plus courte en octets l'emporte.
    Ne laissez pas les langues de golf de code vous décourager de publier des réponses avec des langues non-golfeur de code. Essayez de trouver une réponse aussi courte que possible pour «n'importe quel» langage de programmation.
  • Les règles standard s'appliquent à votre réponse, vous êtes donc autorisé à utiliser STDIN / STDOUT, des fonctions / méthodes avec les paramètres appropriés, des programmes complets. Ton appel.
  • Failles par défaut sont interdites.
  • Si possible, veuillez ajouter un lien avec un test pour votre code.
  • Veuillez également ajouter une explication si nécessaire.

Cas de test:

Inputs:                              Output:

"Just_A_Test!", true                 " ust    est "     (or " ust    est")
"Just_A_Test!", false                "            "     (or "")
"Aa1!Bb2@Cc3#Dd4$", either           "Aa1!Bb2@Cc3#Dd4$"
"H@$h!n9_!$_fun?", true              " @$ !  _!$_   ?"
"H@$h!n9_!$_fun?", false             "H     9        "  (or "H     9")
"A", true                            "A"
"A", false                           " "                (or "")
"H.ngm.n", true                      "  ngm n"
"H.ngm.n", false                     "       "          (or "")
"H.ngm4n", false                     "H.   4 "          (or "H.   4")
Kevin Cruijssen
la source
Est-il acceptable de sortir le plus / le moins en entrées distinctes? Par exemple, pour le cas de test "le hachage est amusant", peut "H "- on et " 9 "(avec les espaces appropriés) être émis à la place de "H 9"?
AdmBorkBork
@AdmBorkBork Je ne comprends pas ce que vous voulez dire; les deux Het 9font partie des "moins".
Erik the Outgolfer
La valeur d'entrée booléenne peut "max"-elle être / "min", qui est ensuite utilisée pour Math[b]faire référence à Math.maxou Math.min?
Justin Mariner
@JustinMariner Tu sais .. J'ai changé d'avis, désolé. Je suppose que c'est pour JS? Je pense que beaucoup de langages de programmation peuvent utiliser quelque chose comme ça, donc trop de réponses existantes devraient être modifiées. Donc désolé, vous devrez garder le b?"max":"min"dans votre réponse .. C'est une ligne fine, je suppose, peut-être que je devrais simplement utiliser une valeur truey / falsey la prochaine fois ..
Kevin Cruijssen

Réponses:

3

Husk , 27 26 24 22 octets

-2 octets grâce à Zgarb

-2 octets grâce à Leo

Prend au ' 'fur Falseet à 'a'mesure True(dans Husk, les espaces dans Fasly et tous les autres personnages sont Truthy)

Fż▲→ġ#¬Ö#≡⁰Ṫḟë½D±o¬□m;

Essayez-le en ligne!

Comment ça marche?

Fż▲→ġ#¬Ö#≡⁰Ṫḟë½D±o¬□m;   Function, takes a character c and a string S as arguments
                    m;   Wrap each character in S into it's own string
             ë           List of four functions returning booleans:
              ½D±o¬      Lower case?,Upper case?,Digit?,Not alphanumeric?
           Ṫḟ            Outer product with find†
       Ö#≡⁰              Sort on how many characters have the same Truthyness as c
    ġ#¬                  Group strings with equal numbers of spaces
   →                     Take the last group
Fż▲                      Squash it all into one list

est une fonction qui prend un prédicat pet une liste Let renvoie le premier élément Lqui satisfait p. Si aucun élément ne satisfait, pun argument par défaut est retourné. Dans ce cas ' '. En appliquant à une chaîne d'un caractère, nous disons essentiellementif p c then c else ' ' .

Est fonction qui prend une fonction fet deux listes L1, L2. Il retourne un tableau des fappliqués sur toutes les paires de L1et L2. Dans ce cas fest , L1notre liste de 4 fonctions, et L2la liste d'une des chaînes de caractères.

Après Ṫḟnous avons une liste de chaînes où chaque chaîne est le résultat du remplacement de caractères qui ne satisfont pas à l'une des règles par un ' '.

NB: Dans les versions plus récentes de Husk, ġ#¬Ö#≡⁰peut être remplacé par k#≡⁰pour une économie de 3 octets!

H.PWiz
la source
Par curiosité: pourquoi ' 'et 'a'? Peut-être que je comprends mieux quand l'explication est ajoutée, parce que je ne peux pas lire Husk. ;)
Kevin Cruijssen
Agréable! Voici 24 octets en utilisant .
Zgarb
@Zgarb Merci! Je n'ai pas vraiment compris ce Mmmque je faisais moi-même :)
H.PWiz
Malheureusement, cela n'aide pas vraiment avec le golf, mais S`?' pourrait être plus simple?IK'
Leo
J'ai tendance à éviter de l'utiliser I, parfois cela rend l'interprète éternel. Cela semble aussi du gaspillage.
H.PWiz
7

Gelée , 31 octets

ØṖḟØBṭØBUs26¤f€³Lİ⁴¡$ÐṀFf
¹⁶Ç?€

Essayez-le en ligne!

Les valeurs booléennes sont 2et 1(ou toute autre paire paire paire / impaire positive), qui représentent TrueetFalse respectivement. Je vais essayer d'ajouter une explication après avoir joué au golf.

Merci à caird coinheringaahing d' avoir économisé 2 octets et à Lynn d' avoir économisé 4 octets! Merci à l'une des astuces d' Erik , qui m'a inspiré pour économiser 4 octets!

Comment ça fonctionne

Notez que ceci est l'explication de la version 35 octets. Le nouveau fait à peu près la même chose (mais un peu modifié par Lynn), donc je ne le changerai pas.

ØBUs26f€³µ³ḟØBW,µẎLİ⁴¡$ÐṀF - Niladic helper link.
ØB                         - String of base digits: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
                             abcdefghijklmnopqrstuvwxyz'. 
  U                        - Reverse.
   s26                     - Chop into sublists of length 26, preserving shorter
                             trailing substrings.
      f€³                  - For each, keep the common characters with the input.
            ØB             - Base digits.
          ³ḟ               - Get the signs in the input. Filter the characters of the
                             input that aren't alphanumeric.
              W,µẎ         - Concatenate (wrap, two element list, tighten).
                       ÐṀ  - Keep the elements with maximal link value.
                  L        - Length.
                    ⁴¡     - Do N times, where N is the second input.
                   İ       - Inverse. Computes 1 ÷ Length. 2 maps to the length itself,
                             because 1 ÷ (1 ÷ Length) = length; 1 yields
                             (1 ÷ Length), swapping the maximal numbers with minimal ones.
                         F - Flatten.

¹⁶e¢$?€ - Main link.
      € - For each character.
   e¢?  - If it is contained by the last link (called niladically), then:
¹       - Identity, the character itself, else:
 ⁶      - A space.
M. Xcoder
la source
40 octets
caird coinheringaahing
@cairdcoinheringaahing Merci! :) Je voulais jouer cette partie depuis que j'ai posté la réponse, mais je ne pouvais pas comprendre pourquoi cela ne fonctionnait pas ... J'avais un µD étranger :
M. Xcoder
31 octets : générez les classes en tant que ØṖḟØBṭØBUs26¤, puis testez l'appartenance avec fet Çau lieu de e¢$.
Lynn
5

Python 2 , 166 158 octets

t=lambda c:('@'<c<'[','`'<c<'{','/'<c<':',1-c.isalnum())
def f(s,b):x=map(sum,zip(*map(t,s)));print''.join([' ',c][x[t(c).index(1)]==sorted(x)[-b]]for c in s)

Essayez-le en ligne!

TFeld
la source
158 octets
M. Xcoder
@ Mr.Xcoder Merci; Je
viens de recevoir
5

R , 193 186 179 158 octets

-7 octets grâce à NofP et sa suggestion de cbind

-6 octets en utilisant outer, -1 octet de commutation [^a-zA-Z0-9]avec[[:punct:]]

-21 octets grâce à MickyT pour avoir signalé qu'une liste de caractères est autorisée

function(S,B){y=outer(c("[a-z]","[A-Z]","\\d","[[:punct:]]"),S,Vectorize(grepl))
S[!colSums(y[(s=rowSums(y))=="if"(B,max,min)(s),,drop=F])]=" "
cat(S,sep='')}

Vérifier tous les cas de test

Prend 1/Tcomme véridique ( max) et 0/Fcomme falsey ( min), et prendS comme une liste de personnages uniques.

Essayez-le en ligne!

Dans ma version originale (avec les suggestions de NofP), la matrice yest construite en évaluant grepl(regex, S)pour chacun regex, puis en les concaténant ensemble sous forme de colonnes d'une matrice. Il en résulte plusieurs appels àgrepl , mais comme cela Sest résolu, il semblait que quelque chose d'autre devait être fait. Comme je l'ai noté:

Il existe des approches potentiellement plus courtes; mapply, par exemple:

y=mapply(grepl,c("[a-z]","[A-Z]","\\d","[^a-zA-Z0-9]"),list(S))

malheureusement, cela ne sera pas simplifié en tant que matrice dans l'exemple à 1 caractère de "A" .

J'ai utilisé outerplutôt que mapply, qui renvoie toujours un tableau (une matrice dans ce cas), et a été forcé deVectorize grepl , ce qui n'est vraiment qu'unmapply wrapper autour.

J'ai également découvert le groupe de caractères prédéfini [:punct:]qui correspond aux caractères de ponctuation (sans espace, non alphanumériques).

Giuseppe
la source
1
Si vous remplacez la matrice par un cbind, vous pouvez réduire à 186 octets: y = cbind (g ("[az]", S), g ("[AZ]", S), g ("\\ d", S), g ("[^ a-zA-Z0-9]", S))
NofP
@NofP oh, très sympa. De plus, vous pouvez entourer le code avec des crochets (`) pour qu'il s'affiche like this. :)
Giuseppe
Les règles stipulent que vous pouvez utiliser un tableau ou une liste de caractères en entrée, vous pouvez donc probablement supprimer leS=el(strsplit(G,""))
MickyT
@MickyT ah, j'ai oublié ça, merci.
Giuseppe
4

Husk , 31 29 28 octets

SMS?' `ṁ§foSM≠?▲▼⁰M#Kë½D±o¬□

Utilise 0 pour un nombre minimal de caractères et 1 pour un nombre maximal de caractères. Essayez-le en ligne!

Explication

Les listes de fonctions sont cool.

SMS?' `ṁ§foSM≠?▲▼⁰M#Kë½D±o¬□  Inputs are bit B and string S.
                     ë        Make a list L of the four functions
                      ½       is-lowercase-letter,
                       D      is-uppercase-letter,
                        ±     is-digit, and
                         o¬□  not is-alphanumeric.
                  M#          For each of them, take number of matches in S,
              ?▲▼⁰            take maximum or minimum depending on B,
          oSM≠                and mark those entries that are not equal to it.
        §f          K         Remove from L the functions that correspond to marked entries, call the result L2.
                              These functions test whether a character should be replaced by a space.
SM                            Do this for each character C in S:
      `ṁ                      Apply each function in L2 to C and sum the results.
  S?'                         If the result is positive, return space, otherwise return C.
Zgarb
la source
4

Python 2 , 140 octets

g=lambda x:x.isalnum()-~(x>'Z')*x.isalpha()
def f(s,m):k=map(g,s).count;print''.join([' ',c][k(g(c))==sorted(map(k,range(4)))[m]]for c in s)

Essayez-le en ligne!

Jonathan Frech a enregistré un octet. Merci!

Le plus haut est le m=-1plus bas m=0.

Lynn
la source
1
Je pense que vous pouvez enregistrer un octet en le remplaçant +x.isalpha()*-~(x>'Z')par -~(x>'Z')*x.isalpha().
Jonathan Frech du
3

Java (OpenJDK 8) , 448 439 432 362 361 354 352 348 343 320 octets

s->b->{int w[]=new int[4],m=0,n=-1>>>1,l;s.chars().forEach(c->{if(c>96&c<123)w[0]++;else if(c>64&c<91)w[1]++;else if(c>47&c<58)w[2]++;else++w[3];});for(int W:w){m=W>m?W:m;n=W<n?W:n;}l=m-n;m=b?m:n;return l<1?s:s.replaceAll("["+(w[0]!=m?"a-z":"")+(w[1]!=m?"A-Z":"")+(w[2]!=m?"\\d]":"]")+(w[3]!=m?"|[^a-zA-Z0-9]":"")," ");}

Essayez-le en ligne!

Roberto Graham
la source
366 octets
Kevin Cruijssen
Vous pouvez supprimer le +dans \\|+$pour un montant supplémentaire -1 octet.
Kevin Cruijssen
Vous pouvez enregistrer trois octets supplémentaires en remplaçant la dernière partie par String r=(w[0]!=m?"[a-z]|":"")+(w[1]!=m?"[A-Z]|":"")+(w[2]!=m?"[0-9]|":"")+(w[3]!=m?"[^a-zA-Z0-9]|":"");return r.isEmpty()?s:s.replaceAll(r.replaceAll(".$","")," ");}.
Kevin Cruijssen
Oh, et n=s.length()peut être n=-1>>>1pour un -4 supplémentaire.
Kevin Cruijssen
Oh, encore une petite chose au golf: [0-9]->\\d
Kevin Cruijssen
3

Ruby , 118 116 octets

Prend 0(le plus bas) ou -1(le plus haut) pour son deuxième argument.

-2 octets grâce à Lynn.

->s,t{s.gsub(/./){|c|[/\d/,/[a-z]/,/[A-Z]/,/[^\da-z]/i].group_by{|x|s.scan(x).size}.sort[t][1].any?{|x|x=~c}?c:" "}}

Essayez-le en ligne!

Non golfé

->s,t{
  s.gsub(/./) {|c|
    [ /\d/,
      /[a-z]/,
      /[A-Z]/,
      /[^\da-z]/i
    ]
    .group_by {|x| s.scan(x).size }
    .sort[t][1]
    .any? {|x| x =~ c } ? c : " "
  }
}
Jordan
la source
Réponse très cool! Vous pouvez utiliser -1comme valeur «la plus élevée» et remplacer minmax[t]par sort[t].
Lynn
3

Python 2, 190 183 174 173 octets

Merci à Jonathan Frech de l'avoir raccourci

from re import*
def f(i,c):
 q='[a-z]','[A-Z]','\d','[\W_]';l=[len(set(finditer(p,i)))for p in q]
 for j,k in enumerate(l):
	if k-eval(c):i=compile(q[j]).sub(' ',i)
 print i

Cela prend les cordes 'max(l)' et 'min(l)'comme vrai et faux. (Je ne pense pas que cela enfreigne les règles ...?) C'est plus long que les deux autres réponses en python mais différent, alors j'ai pensé le publier. Je ne suis pas un grand golfeur, donc je suppose que cela pourrait être encore amélioré, mais toutes les choses que j'ai essayées n'ont pas fonctionné.

Essayez-le en ligne!

dylnan
la source
Bonjour et bienvenue sur le site! Lorsque j'essaie d'exécuter cela, j'obtiens des erreurs et je ne sais pas vraiment pourquoi. Une raison pourrait en sum(1for m...être sum(1 for m..., mais je pense qu'il y a aussi d'autres problèmes. Pourriez-vous fournir un lien vers un interprète en ligne (tel que tio ) pour montrer comment vous appelez cela et pour montrer que ce n'est pas une erreur?
James
@DJMcMayhem Je viens d'ajouter un lien, merci d'avoir fourni le lien, je ne savais pas comment le faire. Je ne reçois pas d'erreur lorsque je l'exécute là-bas.
dylnan
Ah, je ne pouvais pas dire que vous saisissiez max(l)et en min(l)tant que chaînes, c'est pourquoi je recevais des erreurs. Merci d'avoir clarifié ça! Bien que maintenant, cela soit sur le point de violer la règle n ° 3, `Notez que ces valeurs distinctes doivent être utilisées (quelque peu) comme booléennes`, mais c'est certainement un peu une zone grise.
James
BTW, voici un conseil TIO: si vous placez vos appels de fonction dans le champ de pied de page , ils ne seront pas comptés dans votre nombre d'octets, vous pouvez donc facilement voir combien de temps votre réponse est: Essayez-le en ligne!
James
@DJMcMayhem Ah merci. Je suis d'accord, c'est une sorte de zone grise. Je pourrais prendre 'max' et 'min' comme vrai faux puis faire eval (c + '(l)') qui ajoute 6 octets et semble plus acceptable mais jusqu'à ce que OP rejette ma réponse, je suppose que tout va bien.
dylnan
2

JavaScript (ES6), 151 149 octets

g=
(s,f,a=[/\d/,/[A-Z]/,/[a-z]/,/[_\W]/],b=a.map(r=>s.split(r).length))=>s.replace(/./g,c=>b[a.findIndex(r=>r.test(c))]-Math[f?"max":"min"](...b)?' ':c)
<input id=s oninput=o.textContent=g(s.value,f.checked)><input id=f type=checkbox onclick=o.textContent=g(s.value,f.checked)><pre id=o>

Malheureusement, les règles ne me permettent probablement pas de passer Math.maxou Math.mincomme drapeau. Edit: enregistré 2 octets grâce à @JustinMariner.

Neil
la source
1

Gelée , 37 octets

ØWṖs26µẎØṖḟW⁸;
¢f@³L$ÐṂFe@Ѐ³¬¹⁴?a³o⁶

Essayez-le en ligne!

-6 octets "emprunt" au poste d'Erik: D

HyperNeutrino
la source
Lol préserver les espaces est essentiellement la moitié du programme: D
M. Xcoder
Pourriez-vous ajouter une explication, ou travaillez-vous toujours au golf en premier?
Kevin Cruijssen
@KevinCruijssen Golf en premier: D
HyperNeutrino
1

Java (OpenJDK 8) , 307 + 34 306 + 27 295 octets

Ma prise «intéressante» du défi.

Merci à Kevin Cruijssen d' avoir réduit les octets d'importation supprimant complètement l'importation!

s->b->{String t=s.replaceAll("\\d","2").replaceAll("[a-z]","0").replaceAll("[A-Z]","1").replaceAll("\\D","3"),v="";int a[]={0,0,0,0},i=0,z=0,y=-1>>>1;t.chars().forEach(j->{a[j%4]++;});for(int x:a){z=x>z?x:z;y=x<y?x:y;}for(;i<s.length();i++)v+=a[t.charAt(i)%4]!=(b?z:y)?" ":s.charAt(i);return v;}

Essayez-le en ligne!

Explication:

String t=s.replaceAll("\\d","2")
          .replaceAll("[a-z]","0")
          .replaceAll("[A-Z]","1")
          .replaceAll("\\D","3")

Remplace d'abord chaque groupe par un entier compris entre 0 et 3 à l'aide d'une expression régulière simple et le stocke dans une nouvelle chaîne.

int a[]={0,0,0,0},m,i=0,z=0,y=-1>>>1;

Initialise un tableau d'entiers ainsi que quelques autres entiers à utiliser ultérieurement. Définit la yvariable à la taille int maximale en utilisant un décalage de bit à droite non signé.

t.chars().forEach(j->{a[j%4]++;});

Pour chaque caractère de la chaîne modifiée, cela utilise sa valeur ASCII modulo 4 pour calculer l'index du tableau susmentionné à incrémenter.

for(int x:a){
    z=x>z?x:z;
    y=x<y?x:y;
}

Cela parcourt ensuite les comptes de chaque groupe stocké dans le tableau et calcule le minimum ( y) et le maximum ( z).

for(;i<s.length();i++)
    v+=a[t.charAt(i)%4]!=(b?z:y)?" ":s.charAt(i);

Parcourt à nouveau chaque caractère de la chaîne, vérifiant si le groupe de ce groupe de caractères est égal au min / max (en utilisant l'astuce modulo mentionnée plus haut). S'il n'est pas égal, un espace est ajouté à la nouvelle chaîne à la place des caractères, sinon le caractère d'origine est ajouté.

return v;

Enfin, retournez la nouvelle chaîne!

Luke Stevens
la source
1
Belle réponse, +1 de ma part! Deux petites choses au golf: import java.util.stream.IntStream;peuvent être import java.util.stream.*;et ,ipeuvent être ,i=0après lesquelles vous pouvez retirer i=0de la boucle for. Oh, et (s,b)->peut l'être s->b->.
Kevin Cruijssen
@KevinCruijssen Merci! Je ne savais pas que tu pouvais enchaîner des lambdas
Luke Stevens
Cela s'appelle le curry. :) Vous pouvez le faire comme ça java.util.function.Function<String, java.util.function.Function<Boolean, String>> g = s->b->{...};.
Kevin Cruijssen du
1
Oh, et une autre chose au golf: IntStream z=IntStream.of(a);m=(b?z.max():z.min()).getAsInt();peut être l=s.length(),x=0,y=let for(int x:a){z=x>z?x:z;y=x<y?x:y;}et (b?z:y), donc vous n'avez plus besoin de l'importation. Mettre tout cela ensemble devient: s->b->{String t=s.replaceAll("\\d","2").replaceAll("[a-z]","0").replaceAll("[A-Z]","1").replaceAll("\\D","3"),v="";int a[]={0,0,0,0},i=0,l=s.length(),z=0,y=l;t.chars().forEach(j->{a[j%4]++;});for(int x:a){z=x>z?x:z;y=x<y?x:y;}for(;i<l;i++)v+=a[t.charAt(i)%4]!=(b?z:y)?" ":s.charAt(i);return v;}( 294 octets ) .
Kevin Cruijssen
1
@KevinCruijssen Oooooh belle réflexion! Je pourrais attendre un peu avant de le changer juste au cas où vous trouveriez autre chose;)
Luke Stevens
1

Bash, 229 227 212 octets

LANG=C;g="A-Z a-z 0-9 !A-Za-z0-9";declare -A H
f()(((i=$2?99:-1));r=$1;for h in $g;{ t=${r//[$h]};t=${#t};(($2?t<i:t>i))&&i=$t&&H=([$h]=1);((t-i))||H[$h]=1;};for h in $g;{((${H[$h]}))||r=${r//[$h]/ };};echo "$r")

Essayez-le en ligne

Nahuel Fouilleul
la source
Je ne sais pas comment les espaces autour des crochets et des blocs carrés fonctionnent dans Bash, mais cela semble toujours fonctionner sans l'espace àf(){(( .
Kevin Cruijssen
1
yes, space is mandatory generally except for (, also 2 bytes could be saved using ( instead of {, degrading performance because creating a subshell
Nahuel Fouilleul
1

PHP, 161 158 bytes

for([,$s,$z]=$argv;~$c=$s[$i++];)foreach([punct,upper,lower,digit]as$f)(ctype_.$f)($c)?$$i=$f:$g[$f]++;while(~$c=$s[$k++])echo$g[$$k]-($z?min:max)($g)?" ":$c;

Run with -nr or try it online.

  • first loop: for each position, remember the group of the character
    and count the occurences of groups that the current character is not in.
    (that negation saved 3 bytes)
  • depending on second parameter, pick min non-count for truthy, max non-count for falsy.
  • second loop: if (group of current character) non-count differs
    from min/max non-count then print space, else print character.
Titus
la source
1
@KevinCruijssen Make sure you have the latest PHP version (7.1.0) selected.
Titus
1

JavaScript (ES6), 139 bytes

s=>b=>s.map(c=>++a[g(c)]&&c,a=[0,0,0,0],g=c=>c>-1?0:/[a-z]/i.test(c)?c<"a"?2:1:3).map(c=>a.map(v=>v-Math[b?"max":"min"](...a))[g(c)]?" ":c)

Input and output is an array of characters. Takes actual boolean values for input.

A different approach from @Neil's answer; almost avoiding regular expressions. Instead, I used a series of checks to determine the category of each character:

  • Digits return true for c>-1 because non-digits fail mathematical comparisons
  • Uppercase letters match the regex /[a-z]/i and have codepoints less than "a"
  • Lowercase letters match that regex but have codepoints not less than "a"
  • Symbols pass none of those tests

Test Cases

Justin Mariner
la source