Permutazione del caso


27

Chi deve confrontare le cose in modo insensibile quando si è in grado di generare ogni permutazione di maiuscole e minuscole? Nessuno! Questa è la risposta Nessuno lo fa. Il tuo compito è raggiungere questa impresa; genera tutte le possibili permutazioni di maiuscole / minuscole per un dato input.

Ingresso

Una stringa di caratteri ASCII standard stampabili. L'immissione non dovrebbe essere considerata tutta in minuscolo. L'input sarà sempre almeno un carattere.

Produzione

Ogni permutazione di lettere maiuscole e minuscole per la stringa immessa (senza duplicati). Questo dovrebbe cambiare solo i caratteri con una versione piccola e grande (i numeri rimarranno gli stessi). Ogni permutazione deve essere emessa come una stringa o un elenco di caratteri; gli elenchi di stringhe singleton non sono consentiti.

Esempi

a1a
['a1a', 'a1A', 'A1a', 'A1A']

abc
['abc', 'abC', 'aBc', 'aBC', 'Abc', 'AbC', 'ABc', 'ABC']

Hi!
['hi!', 'hI!', 'Hi!', 'HI!'] 

punteggio

Questo è , quindi vince la risposta più breve (in byte).

Come extra divertente vedi quanto ulteriore sforzo ci vorrà per gestire i caratteri ASCII estesi, ecco un ulteriore test case:

ž1a -> ['ž1a', 'ž1A', 'Ž1a', 'Ž1A']

(il tuo programma non ha bisogno di supportare questo)


10
Interessante test case Unicode: Σ['Σ', 'σ', 'ς']
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

Possiamo usare un elenco di caratteri anziché una stringa? Ad esempio, se Hi!dato {('H', 'i', '!'), ('h', 'I', '!'), ('h', 'i', '!'), ('H', 'I', '!')}sarebbe accettabile?
DJMcMayhem

@DrGreenEggsandHamDJ Elenco di caratteri consentito per impostazione predefinita . In Python, tuttavia, queste sono stringhe singleton, il che è diverso.
Dennis,

1
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ ancora più interessante è che Σè la versione maiuscola all'inizio di una parola, σè la versione minuscola all'inizio o al centro ma non alla fine di una parola, ed ςè la versione minuscola solo alla fine di una parola.
FantaC,

1
@DomHastings Come in un elenco e stai solo delimitando lo spazio dell'output? Mi sembra ragionevole.
Colpisci

Risposte:


11

Pyth, 13 12 11

{msrVQd^U2l

1 byte grazie a Leaky Nun!

Un altro byte grazie a Jakube!

Provalo qui o esegui una Test Suite

Creiamo un elenco di elenchi Valori Veri / Falsi prendendo il prodotto cartesiano dell'elenco [0, 1]con se stesso un numero di volte pari alla lunghezza della stringa di input. Quindi ciascuna delle liste secondarie ha la stessa lunghezza della stringa di input. Quindi applichiamo la rfunzione come operazione vettoriale sull'input e l'elenco, quindi otteniamo r letter valueper ciascun elemento secondario. rcon il secondo argomento zero è in minuscolo e con uno è in maiuscolo. Questo crea duplicati su non lettere, il che significa che dobbiamo rimuovere i duplicati dal risultato.



@LeakyNun Ah, ci avevo provato ma per qualche motivo ho pensato di usarli Mentrambi sed .nera della stessa lunghezza. Mi sembra di essere bravo a contare. Comunque, modificando ora, grazie!
FryAmTheEggman,

Sì, hanno la stessa lunghezza, ho appena cambiato l'ultima parte
Leaky Nun,

{msrVQd^U2lè un po 'più corto.
Jakube,

@Jakube Grazie! L'uso Vè piuttosto subdolo, non credo che ci avrei mai pensato qui.
FryAmTheEggman,

8

Gelatina , 6 byte

żŒsŒpQ

Questo è un collegamento monadico (funzione) che prevede una stringa come argomento sinistro e restituisce un elenco di stringhe.

Gestisce caratteri non ASCII. Provalo online!

Come funziona

żŒsŒpQ  Monadic link. Argument: s (string)

 Œs     Swapcase; change the case of all letters in s.
ż       Zipwith; pair each character with itself with changed case.
   Œp   Take the Cartesian product of all pairs.
     Q  Unique; deduplicate the Cartesian product.

3
Ottieni altre lingue: p
Adnan,

2
Anche dopo aver guardato la tabella codici, mi sorprende il fatto che vedo costantemente Jelly con il numero di byte più basso nelle sfide del code golf.
Colpisce

5

Python, 74 71 byte

f=lambda s:s and{r[0]+t for r in{s,s.swapcase()}for t in f(s[1:])}or{s}

Gestisce caratteri non ASCII. Provalo su Ideone .


5

Oracle SQL 11.2, 276 byte

WITH v AS(SELECT SUBSTR(:1,LEVEL,1)c,ROWNUM p FROM DUAL CONNECT BY LEVEL<=LENGTH(:1))SELECT w FROM(SELECT REPLACE(SYS_CONNECT_BY_PATH(c,','),',','')w FROM(SELECT UPPER(c)c,p FROM v UNION SELECT LOWER(c),p FROM v)START WITH p=1CONNECT BY PRIOR p=p-1)WHERE LENGTH(:1)=LENGTH(w);

Un-golfed

WITH v AS
( -- Split input into an array of characters 
  SELECT SUBSTR(:1,LEVEL,1)c,ROWNUM p FROM DUAL CONNECT BY LEVEL<=LENGTH(:1)
)
SELECT w 
FROM   ( -- Build every string combination
         SELECT REPLACE(SYS_CONNECT_BY_PATH(c,','),',','')w 
         FROM   ( -- Merge upper and lower arrays, keep same position for each character, it allows to mix cases
                  SELECT UPPER(c)c,p FROM v UNION SELECT LOWER(c),p FROM v
                )
         START WITH p=1          -- Start with first character (either lowercase or uppercase)
         CONNECT BY PRIOR p=p-1  -- Add the next character (either lowercase or uppercase)
       )
WHERE LENGTH(:1)=LENGTH(w); -- Keep only full strings

Brutto da morire, deve essere più golfabile.


4

05AB1E, 17 byte

Codice:

vyDš‚N0Êiâvy˜J})Ù

Ha spiegato:

vy                     # for each character in input
  Dš‚                  # create a pair of different case, eg: ['ž', 'Ž']
     N0Êiâ             # for all pairs but the first, take cartesian product
                         result will be a list of layered lists eg: [['ž', '1'], 'a'] 
            vy         # for each such list
              ˜J}      # deep flatten and join as a string eg: ž1a
                 )Ù    # wrap in array and remove duplicates

Provalo online


4

Brachylog , 25 22 byte

:ef:1fd.
:2ac.
@u.|@l.

Funziona così come i predicati minuscoli / maiuscoli di Prolog, quindi funziona anche su lettere non ASCII:

?- run("ž1a",Z).
Z = ["Ž1A", "Ž1a", "ž1A", "ž1a"] .

Spiegazione

A differenza di tutte le altre risposte dal momento in cui sto postando questo, questo non utilizza affatto l'approccio cartesiano al prodotto.

  • Predicato principale

    :ef       Split the Input string into a list of 1-char strings
       :1f    Find all valid outputs of predicate 1 with the previous list
              of outputs as input
          d.  Unify the Output with that list excluding all duplicates
    
  • Predicato 1

Questo è usato per applicare maiuscole o minuscole su ciascun carattere dell'input, calcolando così una possibile permutazione. L'uso di findall su questo predicato nel predicato principale consente di calcolare tutte le possibili permutazioni (con alcuni duplicati).

    :2a       Apply predicate 2 on the each element of the Input
       c.     Unify the Output with the concatenation of the elements of
              the previous list
  • Predicato 2

Questo è usato per trasformare un carattere della stringa nella sua versione maiuscola o minuscola.

    @u.       Unify the Output with the uppercase version of the Input
       |      Or
        @l.   Unify the Output with the lowercase version of the input

4

Haskell, 69 58 byte

import Data.Char
mapM(\x->toLower x:[toUpper x|isAlpha x])

Provalo online!

Modifica: @Angs ha salvato 11 byte. Grazie!


mapM(\x->toLower x:[toUpper x|isAlpha x])dovrebbe sbarazzarsi dell'altra importazione?
Angs

3

MATL , 13 byte

tYov!Z}N$Z*Xu

Provalo online!

Spiegazione

t       % Implicit input string. Duplicate
Yo      % Change case of string
v       % Concatenate as a 2xN char array, where N is input length
!       % Transpose: Nx2 char array. Each row has different case, if letter
Z}      % Split into rows: gives N strings of 2 chars. Each char has different 
        % case if it's a letter, or is repeated otherwise
N$      % Specify N inputs for next function
Z*      % Cartesian product of the N strings. Each combination is a row.
        % Repeated chars (i.e. non-letters) give rise to duplicate rows.
Xu      % Remove duplicate rows. Implicit display

3

JavaScript (Firefox 30-57), 92 90 byte

f=([c,...s])=>c?[for(t of f(s))for(d of new Set(c.toUpperCase()+c.toLowerCase()))d+t]:['']

Modifica: salvato 2 byte perché new Setestrarrà felicemente i caratteri univoci da una stringa.


Quando !c sè anche []così puoi [s]invece tornare
l4m2

f=([c,...s])=>c?[for(t of f(s))for(d of new Set(c.toUpperCase()+c.toLowerCase()))d+t]:[s]
l4m2

3

Perl 6 , 37 byte

{[X~] '',|.comb.map:{unique .lc,.uc}}

Provalo

Spiegazione:

{
  [X[~]]                     # cross combine using &infix:<~> operator
    '',                      # empty string so that 1 character strings work
    |                        # flatten the following into outer list
      .comb                  # get every character from input string
      .map:                  # and map it with:
        { unique .lc, .uc }
}

Test:

#! /usr/bin/env perl6

use v6.c;
use Test;

my &case-permutation = {[X~] '',|.comb.map: {unique .lc,.uc}}

my @tests = (
  'a1a' => <a1a a1A A1a A1A>,
  'abc' => <abc abC aBc aBC Abc AbC ABc ABC>,
  'Hi!' => <hi! hI! Hi! HI!>,
  'ž1a' => 1a ž1A Ž1a Ž1A>,
);

plan +@tests;

for @tests -> $_ (:key($input),:value($expected)) {
  is case-permutation($input).sort, $expected.sort, .gist
}
1..4
ok 1 - a1a => (a1a a1A A1a A1A)
ok 2 - abc => (abc abC aBc aBC Abc AbC ABc ABC)
ok 3 - Hi! => (hi! hI! Hi! HI!)
ok 4 - ž1a => (ž1a ž1A Ž1a Ž1A)

È possibile salvare un byte credo: {[X~] '',|.comb.map:{unique .lc,.uc}}(rimuovere lo spazio dopo map:)
Conor O'Brien,


2

Python, 69 byte

import itertools as i;f=lambda s:set(i.product(*zip(s,s.swapcase())))

Ciò restituisce tuple di stringhe singleton anziché stringhe. Non sono sicuro che sia permesso.
Dennis,

Salvare 1 byte utilizzando from itertools import*;e omettendo ili.
Byte Commander il

OP ha affermato che le stringhe singleton non sono consentite. È necessario aggiornare questa risposta.
DJMcMayhem

Il requisito di output è ambiguo (lo è ancora). Dopo che l'ho pubblicato, l'OP è stato chiarito nei commenti. Devo solo eliminare questa risposta? Qual è il protocollo corretto?
Root Due

2

In realtà, 28 byte

;╗l2r∙`"'Ö*£"£M╜@Z"iƒ"£MΣ`M╔

Provalo online!

Questo programma può gestire caratteri non ASCII, grazie alla magia di Python 3.

Spiegazione:

;╗l2r∙`"'Ö*£"£M╜@Z"iƒ"£MΣ`M╔
;╗                            save a copy of input to reg0
  l                           length of input
   2r                         [0,1]
     ∙                        Cartesian product with self (length of input) times
      `                  `M   map:
       "'Ö*£"£M                 push `Ö` (swapcase) if 1 else `` for each value in list
               ╜@Z              zip with input
                  "iƒ"£M        swap the case of those values
                        Σ       join string
                           ╔  unique elements

2

C 229 252 byte

i,n,j,k,l;f(char *s){l=strlen(s);for(i=0;i<l;i++)s[i]=tolower(s[i]);int v[l];for(i=0;i<l;i++)v[i]=0;for(i=0;i<pow(2,l);i++){n=i,k=0;for(;n;k++){v[k]=n;n/=2;}for(j=0;j<l;j++){v[j]%=2;if(v[j])s[j]=toupper(s[j]);else s[j]=tolower(s[j]);}printf("%s ",s);}}

Versione non golfata:

void f(char *s)
{
  int i,num,k,l=strlen(s);
  for(i=0;i<l;i++)
     s[i]=tolower(s[i]);

   int v[l];
   for(i=0;i<l;i++) 
     v[i]=0;   

   for(i=0;i<pow(2,l);i++)
   {
      num=i,k=0;
      for(;num;k++)
      {
         v[k]=num;
         num/=2;        
      } 

      for(int j=0;j<l;j++)
      {
        v[j]%=2;

        if(v[j])
         s[j]=toupper(s[j]);
        else
         s[j]=tolower(s[j]);

      }
      printf("%s \n",s);       

   } 
}

Spiegazione:

  • Accetta la stringa di caratteri, converti la stringa in minuscolo.
  • Dichiarare un array intero di lunghezza uguale a quello della stringa. Riempilo con zeri.
  • Memorizza i numeri da 0 a 2^strlen(s)in forma binaria in un intarray (per una stringa di 3 byte: 000,001,010 ... 111)
  • A seconda che sia impostato un bit in una posizione o, attiva o disattiva il caso.
  • Emette la stringa per ogni possibile combinazione.

Provalo online!


Quando inizialmente l'ho fatto in vb6 come 10 anni fa, credo che la mia soluzione fosse simile a questa. Hai riportato alcuni ricordi;)
Colpisci il

@Poke Sono contento di aver potuto! :)
Abel Tom,

Alcune cose da giocare a golf: rimuovere gli i++in-loop e utilizzarli ++direttamente, oltre a posizionare alcune parti all'interno del for-loop per rimuovere staffe e semicolonne dove possibile. Inoltre, è possibile rimuovere lo spazio nel parametro e utilizzare un'assegnazione ternaria-if alla fine. In totale: i,n,j,k,l;f(char*s){l=strlen(s);for(i=0;i<l;)s[i]=tolower(s[i++]);int v[l];for(i=0;i<l;)v[i++]=0;for(i=0;i<pow(2,l);){for(n=i++,k=0;n;n/=2)v[k++]=n;for(j=0;j<l;j++){v[j]%=2;s[j]=v[j]>0?toupper(s[j]):tolower(s[j]);}printf("%s ",s);}}( -20 byte / 232 byte )
Kevin Cruijssen,

1

Hoon , 242 byte

|=
t/tape
=+
l=(reap (pow 2 (lent t)) t)
%+
roll
(gulf 0 (dec (lent l)))
|=
{a/@ b/(set tape)}
=+
%+
turn
(gulf 0 (dec (lent t)))
|=
n/@
=+
t=(snag n t)
=+
k=(trip t)
?:
=(0 (cut 0 n^1 a))
?:
=((cuss k) t)
(cass k)
(cuss k)
t
(~(put in b) -)

Ungolfed:

|=  t/tape
=+  l=(reap (pow 2 (lent t)) t)
%+  roll  (gulf 0 (dec (lent l)))
|=  {a/@ b/(set tape)}
    =+  %+  turn  (gulf 0 (dec (lent t)))
      |=  n/@
      =+  t=(snag n t)
      =+  k=(trip t)
      ?:  =(0 (cut 0 n^1 a))
        ?:  =((cuss k) t)
              (cass k)
        (cuss k)
      t
    (~(put in b) -)

Sfortunatamente, non sono sicuro di quanto potrebbe essere più piccolo.

Innanzitutto, impostiamo luguale a un elenco con 2 ^ (lunghezza t) ripetizioni di t. Hoon non ha una facfunzione nello stdlib, ma 2 ^ n è sempre più grande di n !, quindi semplicemente setmappiamo l'elenco più grande e usiamo una (hashmap) per de-duplicare le voci.

Ripieghiamo quindi l'elenco [0 .. (lunghezza l)], accumulando in a (set tape). Dobbiamo fare questo invece di mappare ldirettamente perché dobbiamo anche sapere quale sia la ripetizione numerica ( a), ma non possiamo semplicemente incrementare un accumulatore perché Hoon è un linguaggio puro.

Mappiamo su [0 .. (lunghezza t)] (di nuovo in modo da avere l'indice corrente), impostando tl'ennesimo carattere nella stringa, controllando se l'ennesimo ciao ae invertendo il caso (imprecazione o cass, a seconda se cambia o no). Il tipo di ritorno di questa mappa è a tape.

Quindi inseriamo la stringa nella nostra hashmap e restituiamo la hashmap di tutte le stringhe.


"2 ^ n è sempre più grande di n!". In realtà n! > 2^n, a condizione che nsia almeno 4. (Dimostrare per induzione, con caso base n=4.) En.wikipedia.org/wiki/...
mathmandan

1

C, 216 byte

k,i,j,p,n,m;z(char *c){n=-1;m=0;while(c[++n])if(c[n]>64&c[n]<90)c[n]+=32;else if(c[n]<'a'|c[n]>'z')m++;k=1<<(n-m);for(j=0;j<k;j++){for(i=0;i<n;i++){p=1<<i;putc((j&p)==p?toupper(c[i]):c[i],stdout);}putc(0xa,stdout);}}

Questo è un approccio diverso , lo stesso approccio dell'altra risposta C.

Devo eliminare questo e metterlo sotto l'altra risposta come commento?

Lasciami spiegare con la versione Ungolfed

k,i,j,p,n,m;
z(char * c) {
    int n=-1;       // We start at -1 because of forward incrementation
    int m=0;        // this will count the characters we don't have to manipulate
    while(c[++n])   // go until we reach '\0'
    {
        if(c[n]>='a'&c[n]<='z')c[n]-=32; // If we are lower case, then convert
        else if(c[n]<'A'|c[n]>'Z')m++;   // If we are neigther lower case
                                         // nor upper, then make a note
    }

    // get 2 ^ ("length" - "number of invonvertibles")
    k=1<<(n-m); 
    for(j=0;j<k;j++) {      // go through the combinations
        for(i=0;i<n;i++) {  // for each combination go though the characters
            p=1<<i;         // for each character get it's bit position
            putc(
                // if the bit position is set (==1) 
                (j&p)==p ?
                   tolower(c[i]) // convert
                   : c[i], // else: don't
                stdout);
        }
        putc(0xa, stdout);  // print a newline
    }
}

1

Python3, 96 byte

i=input().lower()
for l in{*__import__('itertools').product(*zip(i,i.upper()))}:print(*l,sep='')

In ritardo alla festa, ma ho ancora provato. Grazie a DLosc per avermi ricordato ciò che mi mancava, dandomi consigli sul golf e salvandomi un sacco di byte. :)


@DLosc Grazie per i suggerimenti! Aggiungerò queste funzionalità in :) :)
Blocca il

Grazie per i suggerimenti Mi ha davvero aiutato. Sebbene se uso {} invece di set (), il ciclo passa attraverso il set anziché i prodotti (spero che abbia senso). Almeno sulla mia implementazione (sto usando QPython su Android), {} inserisce semplicemente l'elenco in un set invece di convertirlo in un set.
Blocca il

Ho provato in entrambi i modi e fare {* expr} mi dà un SyntaxError.
Blocca il

Ahhhh. Ecco perchè. L'ultima versione di QPython è su 3.3 o qualcosa del genere.
Blocca il

Ecco qua: provalo online! (Anche corretto un bug e golfato uno spazio.)
DLosc



1

Tcl, 165 181 byte

set n -1
while {[incr n]<1<<[llength [set s [split $argv {}]]]} {puts [join [lmap c $s b [split [format %0[llength $s]b $n] {}] {string to[expr $b?{u}:{l}] $c}] ""]}

Miglioramenti grazie a sergiol . Risposta precedente:

set s [split $argv {}]
set n -1
while {[incr n]<1<<[llength $s]} {set r ""
foreach c $s b [split [format %0[llength $s]b $n] {}] {set r $r[string [expr $b?{tou}:{tol}] $c]}
puts $r}

Utilizza un numero binario per scegliere tra maiuscole / minuscole durante la creazione del testo di output.



@sergiol È abbastanza diverso dal mio che dovresti pubblicarlo come risposta personale e ottenere una buona reputazione per essere fantastico.
Dúthomhas,

No. Ho cambiato solo parti minori della tua risposta, non ho cambiato l'approccio né gli algoritmi essenziali, quindi, dal mio punto di vista, ho pensato che non meritassi di creare una nuova risposta dalla tua! E dubito che potrei ottenere un algoritmo corto come il tuo originale per lo stesso scopo!
sergiol


1

Attache , 39 byte

&Cross[Sum@V]##Unique@V#SwapCase=>Chars

Provalo online!

Simile alla risposta perl. (Ho perso la mia alternativa più interessante, dovrei postare quelli nelle prossime ore.)


0

JavaScript (ES6), 103

Gestisce caratteri non ASCII

(a,r=new Set)=>a?f(a.slice(1)).map(v=>(C=o=>r.add(a[0][`to${o}erCase`]()+v),C`Upp`,C`Low`))&&[...r]:[a]

Test

f=(a,r=new Set)=>a?f(a.slice(1)).map(v=>(C=o=>r.add(a[0][`to${o}erCase`]()+v),C`Upp`,C`Low`))&&[...r]:[a]

function test() { O.textContent = f(I.value).join('\n') }

test()
<input id=I oninput='test()' value='ž1a'>
<pre id=O></pre>

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.