Permutação de Caso


27

Quem precisa comparar as maiúsculas e minúsculas quando você é capaz de gerar todas as permutações de maiúsculas e minúsculas? Ninguém! Essa é a resposta. Ninguém faz. Sua tarefa é conseguir esse feito; gere todas as permutações possíveis de maiúsculas / minúsculas para uma determinada entrada.

Entrada

Uma sequência de caracteres ASCII padrão imprimíveis. A entrada não deve ser assumida como minúscula. A entrada sempre terá pelo menos um caractere.

Saída

Toda permutação de maiúsculas e minúsculas para a sequência inserida (sem duplicatas). Isso deve mudar apenas caracteres com uma versão pequena e grande (os números permanecerão os mesmos). Cada permutação deve ser impressa como uma string ou uma lista de caracteres; listas de strings singleton não são permitidas.

Exemplos

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

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

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

Pontuação

Isso é , então a resposta mais curta (em bytes) vence.

Como um divertido extra, veja quanto esforço adicional será necessário para lidar com os caracteres ASCII estendidos, aqui está um caso de teste extra:

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

(seu programa não precisa suportar isso)


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

Podemos usar uma lista de caracteres em vez de uma string? Por exemplo, se Hi!deu {('H', 'i', '!'), ('h', 'I', '!'), ('h', 'i', '!'), ('H', 'I', '!')}, isso seria aceitável?
DJMcMayhem

@DrGreenEggsandHamDJ A lista de caracteres é permitida por padrão . No Python, essas são sequências singleton, o que é diferente.
Dennis

1
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ ainda mais interessante é que Σé a versão em maiúscula no início de uma palavra, σé a versão em minúscula no início ou no meio, mas não no final de uma palavra, e ςé a versão em minúscula apenas no final de uma palavra.
FantaC

1
@DomHastings Como você tem uma lista e está delimitando apenas o espaço? Isso me parece razoável.
Poke

Respostas:


11

Pyth, 13 12 11

{msrVQd^U2l

1 byte graças a Leaky Nun!

Outro byte graças a Jakube!

Experimente aqui ou execute um Conjunto de Testes

Criamos uma lista de valores True / False de listas, levando o produto cartesiano da lista [0, 1]consigo várias vezes igual ao comprimento da string de entrada. Portanto, cada uma das sublistas tem o mesmo comprimento que a sequência de entrada. Em seguida, aplicamos a rfunção como uma operação vetorial sobre a entrada e a lista, para obtermos r letter valuecada subelemento. rcom o segundo argumento, zero é minúsculo e, com um, maiúsculo. Isso cria duplicatas sem letras, o que significa que precisamos remover duplicatas do resultado.



@LeakyNun Ah, eu tinha tentado isso, mas por algum motivo pensei Mem usar os dois se .ntinha o mesmo comprimento. Eu pareço ser bom em contar. Enfim, editando agora, obrigado!
FryAmTheEggman 31/05

Sim, eles são o mesmo comprimento, eu só mudou a última parte
Leaky Nun

{msrVQd^U2lé um pouco mais curto.
Jakube

@Jakube Thanks! Usar Vé bem sorrateiro, acho que nunca teria pensado nisso aqui.
FryAmTheEggman

8

Gelatina , 6 bytes

żŒsŒpQ

Este é um link monádico (função) que espera uma string como argumento à esquerda e retorna uma lista de strings.

Manipula caracteres não ASCII. Experimente online!

Como funciona

żŒ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
Obtenha rekt outros idiomas: p
Adnan

2
Mesmo depois de olhar para a página de códigos, o fato de eu sempre ver Jelly com a menor contagem de bytes em desafios de código-golfe me surpreende.
Puxão

5

Python, 74 71 bytes

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

Manipula caracteres não ASCII. Teste em Ideone .


5

Oracle SQL 11.2, 276 bytes

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);

Sem golfe

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

Feio como o inferno, deve ser mais jogável.


4

05AB1E, 17 bytes

Código:

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

Explicado:

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

Experimente online


4

Braquilog , 25 22 bytes

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

Isso funciona bem como os predicados em letras minúsculas / maiúsculas do Prolog, portanto, também funciona em letras não ASCII:

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

Explicação

Diferente de todas as outras respostas no momento em que estou postando isso, isso não usa a abordagem do produto cartesiano.

  • Predicado Principal

    :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
    
  • Predicado 1

Isso é usado para aplicar maiúsculas ou minúsculas em cada caractere da entrada, calculando assim uma permutação possível. O uso de findall nesse predicado no predicado principal permite calcular todas as permutações possíveis (com algumas duplicatas).

    :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
  • Predicado 2

Isso é usado para transformar um caractere da string em sua versão maiúscula ou minúscula.

    @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 bytes

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

Experimente online!

Edit: @Angs salvou 11 bytes. Obrigado!


mapM(\x->toLower x:[toUpper x|isAlpha x])deve se livrar da outra importação?
Angs

3

MATL , 13 bytes

tYov!Z}N$Z*Xu

Experimente online!

Explicação

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 bytes

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

Editar: salvou 2 bytes porque new Set, felizmente, extrairá os caracteres exclusivos de uma string.


Quando !c sé também []para que você possa voltar [s]vez
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 bytes

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

Tente

Explicação:

{
  [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 }
}

Teste:

#! /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)

Você pode salvar um byte eu penso: {[X~] '',|.comb.map:{unique .lc,.uc}}(espaço retirar após map:)
Conor O'Brien


2

Python, 69 bytes

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

Isso retorna tuplas de strings singleton em vez de strings. Não tenho certeza se isso é permitido.
Dennis

Economize 1 byte usando from itertools import*;e omitindo oi.
Byte Commander

O OP disse que seqüências de caracteres singleton não são permitidas. Você deve atualizar esta resposta.
DJMcMayhem

O requisito de saída é ambíguo (ainda é). Depois que postei isso, o OP esclareceu nos comentários. Devo apenas excluir esta resposta? Qual é o protocolo adequado?
precisa saber é o seguinte

2

Na verdade, 28 bytes

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

Experimente online!

Este programa pode lidar com caracteres não ASCII, graças à magia do Python 3.

Explicação:

;╗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 bytes

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);}}

Versão não destruída:

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);       

   } 
}

Explicação:

  • Aceite a cadeia de caracteres, converta-a em minúsculas.
  • Declare um array inteiro de comprimento igual ao da string. Preencha com zeros.
  • Armazene os números de 0 a 2^strlen(s)em formato binário em uma intmatriz (para uma sequência de 3 bytes: 000,001,010 ... 111)
  • Dependendo se um pouco em uma posição estiver definido ou alterne o caso.
  • Saída da string para todas as combinações possíveis.

Experimente online!


Quando eu fiz isso originalmente no vb6 há 10 anos, acredito que minha solução era semelhante a esta. Você trouxe de volta algumas lembranças;)
Poke

@Poke Fico feliz que eu poderia! :)
Abel Tom

Algumas coisas para jogar golfe: remova os i++loops for-loops e use-os ++diretamente, além de colocar algumas peças dentro do loop for para remover suportes e semi-colunas sempre que possível. Além disso, você pode remover o espaço no parâmetro e usar uma atribuição ternária se no final. No total: 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 bytes / 232 bytes )
Kevin Cruijssen 22/02

1

Hoon , 242 bytes

|=
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) -)

Infelizmente, não tenho certeza do quanto isso poderia ser menor.

Primeiro, definimos ligual a uma lista com 2 ^ (comprimento t) repetições de t. Hoon não tem uma facfunção no stdlib, mas 2 ^ n é sempre maior que n !, então simplesmente setmapeamos a lista maior e usamos um (mapa de hash) para desduplicar as entradas.

Em seguida, dobramos a lista [0 .. (comprimento l)], acumulando-se em a (set tape). Precisamos fazer isso em vez de mapear ldiretamente, porque também precisamos saber qual é a repetição de número ( a), mas não podemos simplesmente incrementar um acumulador porque Hoon é uma linguagem pura.

Mapeamos sobre [0 .. (length t)] (novamente, para que tenhamos o índice atual), definindo to enésimo caractere na string, verificando se o enésimoésimo bye ae invertendo o caso (cuss ou cass, dependendo se ele mudar ou não). O tipo de retorno deste mapa é a tape.

Em seguida, colocamos a string em nosso hashmap e retornamos o hashmap de todas as strings.


"2 ^ n é sempre maior que n!". Na verdade n! > 2^n, desde que nseja pelo menos 4. (Provar por indução, com base de caso n=4.) En.wikipedia.org/wiki/...
mathmandan

1

C, 216 bytes

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);}}

Esta é uma abordagem diferente , a mesma abordagem que a outra resposta C.

Devo excluir isso e colocá-lo na outra resposta como um comentário?

Deixe-me explicar com a versão 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 bytes

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

Tarde para a festa, mas ainda tinha chance. Agradeço ao DLosc por me lembrar as coisas que perdi, por me dar dicas de golfe e por me economizar um monte de bytes. :)


@DLosc Obrigado pelas dicas! Vou adicionar esses recursos. :)
Blocos

Obrigado pelas dicas. Isso realmente ajudou. Embora se eu usar {} em vez de set (), o loop percorrerá o conjunto em vez dos produtos (espero que faça sentido). Pelo menos na minha implementação (estou usando o QPython no Android), {} apenas coloca a lista dentro de um conjunto em vez de convertê-la em um conjunto.
Bloqueia

Eu tentei nos dois sentidos e fazer {* expr} me dá um SyntaxError.
Bloqueia

Ahhhh. É por isso. A versão mais recente do QPython está na 3.3 ou algo assim.
Bloqueia

Aqui está: Experimente online! (Também fixo um erro e golfed um espaço.)
DLosc



1

Tcl, 165181 bytes

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}] ""]}

Melhorias graças ao sergiol . Resposta anterior:

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}

Usa um número binário para escolher entre maiúsculas / minúsculas ao criar o texto de saída.



@sergiol Isso é diferente o suficiente para que você deva postar como sua própria resposta e obter um bom crédito por ser incrível.
Dúthomhas 29/04

Não. Eu apenas mudei partes menores da sua resposta, não mudei a abordagem nem os algoritmos essenciais, portanto, no meu ponto de vista, pensei que não merecia criar uma nova resposta para a sua! E duvido que possa obter um algoritmo curto como o original para o mesmo propósito!
Sergiol 29/04



0

JavaScript (ES6), 103

Manipula caracteres não 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]

Teste

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>

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.