Permutación de caso


27

¿Quién necesita comparar las cosas sin distinción entre mayúsculas y minúsculas cuando puede generar cada permutación de mayúsculas y minúsculas? ¡Ninguno! Esa es la respuesta. Nadie hace. Tu tarea es lograr esta hazaña; generar todas las permutaciones posibles de mayúsculas / minúsculas para una entrada dada.

Entrada

Una cadena de caracteres ascii estándar imprimibles. No se debe suponer que las entradas están en minúsculas. La entrada siempre tendrá al menos un carácter.

Salida

Cada permutación de mayúsculas y minúsculas para la cadena ingresada (sin duplicados). Esto solo debería cambiar los caracteres con una versión pequeña y grande (los números seguirán siendo los mismos). Cada permutación se debe generar como una cadena o una lista de caracteres; No se permiten listas de cadenas singleton.

Ejemplos

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

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

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

Tanteo

Este es el , por lo que gana la respuesta más corta (en bytes).

Como un extra divertido, vea cuánto esfuerzo adicional se necesitará para manejar los caracteres ascii extendidos, aquí hay un caso de prueba adicional:

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

(su programa no necesita soportar esto)


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

¿Podemos usar una lista de caracteres en lugar de una cadena? Por ejemplo, si se Hi!da, {('H', 'i', '!'), ('h', 'I', '!'), ('h', 'i', '!'), ('H', 'I', '!')}¿sería aceptable?
DJMcMayhem

@DrGreenEggsandHamDJ La lista de caracteres está permitida de forma predeterminada . Sin embargo, en Python, esas son cadenas singleton, lo cual es diferente.
Dennis

1
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ aún más interesante es que Σes la versión en mayúscula al comienzo de una palabra, σes la versión en minúscula al principio o en el medio pero no el final de una palabra, y ςes la versión en minúscula solo al final de una palabra.
FantaC

1
@DomHastings ¿Como tienes una lista y solo delimitas el espacio de la salida? Eso me parece razonable.
Poke

Respuestas:


11

Pyth 13 12 11

{msrVQd^U2l

¡1 byte gracias a Leaky Nun!

¡Otro byte gracias a Jakube!

Pruébelo aquí o ejecute un Test Suite

Creamos una lista de listas de valores Verdadero / Falso tomando el producto cartesiano de la lista [0, 1]consigo varias veces igual a la longitud de la cadena de entrada. Por lo tanto, cada una de las sublistas tiene la misma longitud que la cadena de entrada. Luego aplicamos la rfunción como una operación vectorial sobre la entrada y la lista, para obtener r letter valuecada subelemento. rcon el segundo argumento cero es minúscula y con uno es mayúscula. Esto crea duplicados en no letras, lo que significa que necesitamos eliminar duplicados del resultado.



@LeakyNun Ah, lo había intentado pero por alguna razón pensé usarlo Men ambos sy .ntenía la misma longitud. Parece que soy bueno contando. De todos modos, editando ahora, ¡gracias!
FryAmTheEggman

Sí, tienen la misma longitud, acabo de cambiar la última parte
Leaky Nun

{msrVQd^U2lEs un poco más corto.
Jakube

@Jakube ¡Gracias! Usar Ves bastante astuto, no creo que haya pensado en eso aquí.
FryAmTheEggman

8

Jalea , 6 bytes

żŒsŒpQ

Este es un enlace monádico (función) que espera una cadena como argumento izquierdo y devuelve una lista de cadenas.

Maneja caracteres no ASCII. Pruébalo en línea!

Cómo 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
Obtenga rekt otros idiomas: p
Adnan

2
Incluso después de mirar la página de códigos, me asombra el hecho de que constantemente veo a Jelly con el menor conteo de bytes en desafíos de código de golf.
Poke

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}

Maneja caracteres no ASCII. Pruébalo en 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);

Sin golf

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

Feo como el infierno, debe ser más golfable.


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

Pruébalo en línea


4

Brachylog , 25 22 bytes

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

Esto funciona tan bien como los predicados en minúsculas / mayúsculas de Prolog, por lo tanto, también funciona en letras no ASCII:

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

Explicación

A diferencia de todas las otras respuestas en el momento en que estoy publicando esto, esto no utiliza el enfoque de producto cartesiano en absoluto.

  • 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

Esto se utiliza para aplicar mayúsculas o minúsculas en cada carácter de la entrada, calculando así una posible permutación. El uso de findall en este predicado en el predicado principal permite calcular todas las permutaciones posibles (con algunos duplicados).

    :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

Esto se utiliza para convertir un carácter de la cadena en su versión en mayúscula o en 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])

Pruébalo en línea!

Editar: @Angs ahorró 11 bytes. ¡Gracias!


mapM(\x->toLower x:[toUpper x|isAlpha x])debería deshacerse de la otra importación?
Angs

3

MATL , 13 bytes

tYov!Z}N$Z*Xu

Pruébalo en línea!

Explicación

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: se guardaron 2 bytes porque new Setextraerá felizmente los caracteres únicos de una cadena.


Cuando !c ses también []para que pueda volver [s]en su lugar
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}}

Intentalo

Explicación:

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

Prueba:

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

Puede guardar un byte, creo: {[X~] '',|.comb.map:{unique .lc,.uc}}(quitar espacio después map:)
Conor O'Brien


2

Python, 69 bytes

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

Eso devuelve tuplas de cadenas singleton en lugar de cadenas. No estoy seguro si eso está permitido.
Dennis

Ahorre 1 byte usando from itertools import*;y omitiendo eli.
Byte Commander

OP ha dicho que las cadenas singleton no están permitidas. Deberías actualizar esta respuesta.
DJMcMayhem

El requisito de salida es ambiguo (todavía lo es). Después de publicar esto, el OP aclaró en los comentarios. ¿Debo eliminar esta respuesta? ¿Cuál es el protocolo apropiado?
RootTwo

2

En realidad, 28 bytes

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

Pruébalo en línea!

Este programa puede manejar caracteres no ASCII, gracias a la magia de Python 3.

Explicación:

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

Versión sin golf:

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

   } 
}

Explicación:

  • Acepte la cadena de caracteres, convierta la cadena a minúsculas.
  • Declare una matriz entera de longitud igual a la de la cadena. Llénalo con ceros.
  • Almacene los números del 0 al 2^strlen(s)binario en una intmatriz (para una cadena de 3 bytes: 000,001,010 ... 111)
  • Dependiendo de si se establece un bit en una posición o, alternar el caso.
  • Salida de la cadena para cada combinación posible.

Pruébalo en línea!


Cuando hice esto originalmente en vb6 como hace 10 años, creo que mi solución fue similar a esta. Has traído algunos recuerdos;)
Poke

@Poke Me alegro de que pude! :)
Abel Tom

Algunas cosas para jugar al golf: quite los i++bucles for y use ++directamente, así como también coloque algunas partes dentro del bucle for para quitar los soportes y las semicolumnas cuando sea posible. Además, puede eliminar el espacio en el parámetro y usar una asignación ternaria si al final. En 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

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

Sin golf:

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

No estoy seguro de cuánto más pequeño podría ser, desafortunadamente.

Primero, establecemos ligual a una lista con 2 ^ (longitud t) repeticiones de t. Hoon no tiene una facfunción en stdlib, pero 2 ^ n siempre es más grande que n !, así que simplemente setasignamos sobre la lista más grande y usamos un (hashmap) para desduplicar entradas.

Luego doblamos la lista [0 .. (longitud l)], acumulando en a (set tape). Necesitamos hacer esto en lugar de mapear ldirectamente porque también necesitamos saber qué repetición de números es ( a), pero no podemos simplemente incrementar un acumulador debido a que Hoon es un lenguaje puro.

Mapeamos sobre [0 .. (longitud t)] (nuevamente para que tengamos el índice actual), estableciendo tel enésimo carácter en la cadena, verificando si el enésimo bye ae invirtiendo el caso (maldición o cass, dependiendo de si cambia o no). El tipo de retorno de este mapa es a tape.

Luego colocamos la cadena en nuestro hashmap y devolvemos el hashmap de todas las cadenas.


"2 ^ n siempre es más grande que n!". En realidad n! > 2^n, siempre que nsea ​​al menos 4. (Demostrar por inducción, con la caja de base 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);}}

Este es un enfoque diferente , el mismo enfoque que la otra respuesta C.

¿Debo eliminar esto y ponerlo debajo de la otra respuesta como comentario?

Déjame explicarte con la versión 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 a la fiesta, pero todavía tenía una oportunidad. Gracias a DLosc por recordarme las cosas que me perdí, darme consejos de golf y ahorrarme un montón de bytes. :)


@DLosc ¡Gracias por los consejos! Agregaré esas características en. :)
Blocks

Gracias por los consejos. Realmente ayudó. Aunque si uso {} en lugar de set (), el ciclo recorre el conjunto en lugar de los productos (espero que tenga sentido). Al menos en mi implementación (estoy usando QPython en Android), {} simplemente coloca la lista dentro de un conjunto en lugar de convertir la lista en un conjunto.
Bloques del

He intentado en ambos sentidos y hacer {* expr} me da un SyntaxError.
Bloquea

Ahhhh Es por eso. La última versión de QPython está en 3.3 o algo así.
Bloquea

Aquí tienes: ¡ Pruébalo en línea! (También reparó un error y jugó un golf.)
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}] ""]}

Mejoras gracias a sergiol . Respuesta 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}

Utiliza un número binario para elegir entre mayúsculas y minúsculas al crear el texto de salida.



@sergiol Eso es lo suficientemente diferente al mío que deberías publicarlo como tu propia respuesta y obtener una buena reputación por ser increíble.
Dúthomhas

No. Solo cambié partes menores de su respuesta, no cambié el enfoque ni los algoritmos esenciales, así que, en mi punto de vista, ¡pensé que no merecía crear una nueva respuesta a partir de la suya! ¡Y dudo que pueda obtener un algoritmo corto como el original para el mismo propósito!
sergiol



0

JavaScript (ES6), 103

Maneja caracteres no 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]

Prueba

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>

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.