Sprawa permutacji


27

Kto musi porównywać sprawy bez rozróżniania wielkości liter, gdy jesteś w stanie wygenerować każdą kombinację wielkich i małych liter? Nikt! To jest odpowiedź. Nikt tego nie robi. Twoim zadaniem jest osiągnięcie tego wyczynu; wygeneruj wszystkie możliwe kombinacje wielkich / małych liter dla danego wejścia.

Wkład

Ciąg standardowych znaków ascii do wydrukowania. Nie należy zakładać, że dane wejściowe są pisane małymi literami. Dane wejściowe zawsze będą zawierać co najmniej jeden znak.

Wydajność

Każda permutacja wielkich i małych liter dla wprowadzonego ciągu (bez duplikatów). Powinno to zmieniać tylko znaki w małej i dużej wersji (liczby pozostaną takie same). Każda permutacja musi być wyprowadzana jako ciąg znaków lub lista znaków; listy ciągów singletonów są niedozwolone.

Przykłady

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

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

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

Punktacja

To jest , więc wygrywa najkrótsza odpowiedź (w bajtach).

Dla zabawy warto zobaczyć, ile dodatkowego wysiłku zajmie obsłużenie rozszerzonych postaci ascii, oto dodatkowy przypadek testowy:

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

(twój program nie musi tego obsługiwać)


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

Czy możemy użyć listy znaków zamiast ciągu? Na przykład, jeśli Hi!dał {('H', 'i', '!'), ('h', 'I', '!'), ('h', 'i', '!'), ('H', 'I', '!')}byłoby to dopuszczalne?
DJMcMayhem

@DrGreenEggsandHamDJ Lista znaków jest domyślnie dozwolona . W Pythonie są to jednak łańcuchy singletonowe, co jest inne.
Dennis

1
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳ jeszcze bardziej interesujące jest to, że Σjest to wersja pisana wielkimi literami na początku słowa, σto wersja pisana małymi literami na początku lub w środku, ale nie na końcu słowa, i ςjest wersją pisaną małymi literami tylko na końcu słowa.
FantaC

1
@DomHastings Jak masz listę i po prostu ograniczasz spacją wynik? Wydaje mi się to rozsądne.
Poke

Odpowiedzi:


11

Pyth 13 12 11

{msrVQd^U2l

1 bajt dzięki Dziurawej Zakonnicy!

Kolejny bajt dzięki Jakube!

Wypróbuj tutaj lub uruchom pakiet testowy

Tworzymy listę wartości True / False, biorąc kartezjański produkt z listy [0, 1]kilka razy równy długości ciągu wejściowego. Zatem każda z list podrzędnych ma taką samą długość jak łańcuch wejściowy. Następnie stosujemy rfunkcję jako operację wektorową na wejściu i liście, więc otrzymujemy r letter valuedla każdego podelementu. rz drugim argumentem zero oznacza małe litery, a jednym - wielkie litery. Powoduje to utworzenie duplikatów w przypadku znaków innych niż litery, co oznacza, że ​​musimy usunąć duplikaty z wyniku.



@LeakyNun Ah, próbowałem tego, ale z jakiegoś powodu pomyślałem, że używam Mobu si .njest tej samej długości. Wydaje mi się, że jestem dobry w liczeniu. W każdym razie, edycja teraz, dzięki!
FryAmTheEggman

Tak, są tej samej długości, właśnie zmieniłem ostatnią część
Leaky Nun

{msrVQd^U2ljest trochę krótszy.
Jakube,

@Jakube Thanks! Używanie Vjest dość podstępne, nie sądzę, żebym kiedykolwiek pomyślał o tym tutaj.
FryAmTheEggman

8

Galaretka , 6 bajtów

żŒsŒpQ

Jest to monadyczny link (funkcja), który oczekuje łańcucha jako lewego argumentu i zwraca listę łańcuchów.

Obsługuje znaki spoza ASCII. Wypróbuj online!

Jak to działa

żŒ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
Uzyskaj inne języki: p
Adnan

2
Nawet po spojrzeniu na stronę kodową zadziwia mnie fakt, że konsekwentnie widzę Jelly z najniższym bajtem liczącym na wyzwania związane z golfem.
Poke

5

Python, 74 71 bajtów

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

Obsługuje znaki spoza ASCII. Przetestuj na Ideone .


5

Oracle SQL 11.2, 276 bajtów

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

Nie grał w golfa

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

Brzydki jak diabli, musi być bardziej golfowy.


4

05AB1E, 17 bajtów

Kod:

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

Wyjaśnił:

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

Wypróbuj online


4

Brachylog , 25 22 bajtów

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

Działa to tak samo jak predykaty małych i wielkich liter w Prologu, dlatego działa również na literach spoza ASCII:

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

Wyjaśnienie

W przeciwieństwie do wszystkich innych odpowiedzi w chwili, gdy to piszę, w ogóle nie wykorzystuje to podejścia kartezjańskiego.

  • Główny predykat

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

Służy to do nakładania górnej lub dolnej obudowy na każdy znak wejściowy, obliczając w ten sposób jedną możliwą permutację. Użycie findall w tym predykacie w głównym predykacie pozwala obliczyć wszystkie możliwe permutacje (z niektórymi duplikatami).

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

Służy to do zamiany znaku ciągu na jego wielką lub małą literę.

    @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 bajtów

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

Wypróbuj online!

Edycja: @Angs zapisał 11 bajtów. Dzięki!


mapM(\x->toLower x:[toUpper x|isAlpha x])powinien pozbyć się drugiego importu?
Angs

3

MATL , 13 bajtów

tYov!Z}N$Z*Xu

Wypróbuj online!

Wyjaśnienie

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 bajtów

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

Edycja: Zapisano 2 bajty, ponieważ new Setz przyjemnością wydobędzie unikatowe znaki z łańcucha.


Kiedy !c sjest również [], abyś mógł [s]zamiast tego wrócić
l4m2

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

3

Perl 6 , 37 bajtów

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

Spróbuj

Wyjaśnienie:

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

Myślę, że możesz zapisać bajt: {[X~] '',|.comb.map:{unique .lc,.uc}}(usuń spację po map:)
Conor O'Brien


2

Python, 69 bajtów

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

Zwraca krotki pojedynczych ciągów zamiast ciągów. Nie jestem pewien, czy to dozwolone.
Dennis

Zaoszczędź 1 bajt, używając from itertools import*;i pomijająci.
Byte Commander

OP powiedział, że łańcuchy singletonów są niedozwolone. Powinieneś zaktualizować tę odpowiedź.
DJMcMayhem

Wymaganie wyjściowe jest niejednoznaczne (nadal jest). Po tym, jak to opublikowałem, PO wyjaśnił w komentarzach. Czy powinienem po prostu usunąć tę odpowiedź? Jaki jest właściwy protokół?
RootTwo

2

Właściwie 28 bajtów

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

Wypróbuj online!

Ten program obsługuje znaki spoza ASCII dzięki magii Python 3.

Wyjaśnienie:

;╗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 bajtów

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

Wersja bez golfa:

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

   } 
}

Wyjaśnienie:

  • Zaakceptuj ciąg znaków, przekonwertuj go na małe litery.
  • Zadeklaruj tablicę liczb całkowitych o długości równej długości łańcucha. Wypełnij go zerami.
  • Przechowuj liczby od 0 do 2^strlen(s)w formie binarnej w inttablicy (dla ciągu 3-bajtowego: 000,001,010 ... 111)
  • W zależności od tego, czy bit w pozycji jest ustawiony lub, przełącz skrzynkę.
  • Wypisuj ciąg dla każdej możliwej kombinacji.

Wypróbuj online!


Kiedy pierwotnie robiłem to w vb6, jak 10 lat temu, uważam, że moje rozwiązanie było podobne do tego. Przywołałeś trochę wspomnień;)
Poke

@Poke Cieszę się, że mogłem! :)
Abel Tom

Niektóre rzeczy do gry w golfa: Usuń i++pętle i użyj ++bezpośrednio, a także umieść niektóre części w pętli, aby usunąć wsporniki i półkolumny, jeśli to możliwe. Możesz również usunąć spację w parametrze i użyć przypisania trójskładnikowego na końcu. Łącznie: 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 bajtów / 232 bajty )
Kevin Cruijssen

1

Hoon , 242 bajtów

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

Nie golfowany:

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

Niestety nie jestem pewien, o ile może być mniejszy.

Najpierw ustawiamy na lrówną listę z 2 ^ (długość t) powtórzeniami t. Hoon nie ma facfunkcji w stdlib, ale 2 ^ n jest zawsze większe niż n !, więc po prostu mapujemy na większej liście i używamy set(hashmap), aby zduplikować wpisy.

Następnie składamy listę [0 .. (długość l)], kumulując się w a (set tape). Musimy to zrobić zamiast mapować lbezpośrednio, ponieważ musimy również wiedzieć, jakie to jest powtarzanie liczb ( a), ale nie możemy po prostu zwiększyć akumulatora, ponieważ Hoon jest czystym językiem.

Mapujemy ponad [0 .. (długość t)] (ponownie, więc mamy bieżący indeks), ustawiając tna n-ty znak w ciągu, sprawdzając, czy n-ty bye ai odwracając wielkość liter (przekrój lub cass, zależnie od tego, czy się zmieni albo nie). Typ zwrotu tej mapy to tape.

Następnie umieszczamy ciąg w naszym haszapie i zwracamy hasztap wszystkich łańcuchów.


„2 ^ n jest zawsze większe niż n!”. Właściwie n! > 2^npod warunkiem, że nprzynajmniej 4. (Udowodnić przez indukcję, w przypadku podstawowym n=4.) En.wikipedia.org/wiki/...
mathmandan

1

C, 216 bajtów

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

Jest to inne podejście , takie samo podejście jak w przypadku innej odpowiedzi C.

Czy powinienem to usunąć i umieścić jako odpowiedź pod inną odpowiedzią?

Pozwól mi wyjaśnić wersję 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 bajtów

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

Późno na imprezę, ale wciąż miałem okazję. Dzięki DLosc za przypomnienie mi rzeczy, które mi umknęły, udzielenie wskazówek golfowych i zaoszczędzenie kilku bajtów. :)


@DLosc Dzięki za wskazówki! Dodam te funkcje w. :)
Blocks

Dzięki za wskazówki. To naprawdę pomogło. Chociaż jeśli użyję {} zamiast set (), pętla przechodzi przez zestaw zamiast produktów (mam nadzieję, że to ma sens). Przynajmniej w mojej implementacji (używam QPython na Androida) {} po prostu umieszcza listę w zestawie zamiast konwertować listę do zestawu.
Blokuje

Próbowałem obu sposobów i wykonanie {* expr} daje mi błąd SyntaxError.
Blokuje

Ahhh Dlatego. Najnowsza wersja QPython jest w wersji 3.3 lub coś takiego.
Blokuje

Proszę bardzo: wypróbuj online! (Naprawiono także błąd i grałem w golfa.)
DLosc



1

Tcl, 165 181 bajtów

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

Ulepszenia dzięki sergiolowi . Poprzednia odpowiedź:

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}

Używa liczby binarnej do wybierania między dużymi / małymi literami podczas tworzenia tekstu wyjściowego.



@sergiol To na tyle różni się od mojego, że powinieneś opublikować go jako własną odpowiedź i zdobyć uznanie za bycie niesamowitym.
Dúthomhas,

Nie. Zmieniłem tylko drobne części twojej odpowiedzi, nie zmieniłem podejścia ani podstawowych algorytmów, więc z mojego punktu widzenia myślałem, że nie zasłużyłem na stworzenie nowej odpowiedzi z twojego! I wątpię, czy mógłbym uzyskać krótki algorytm jak twój oryginalny do tego samego celu!
sergiol


1

Attache , 39 bajtów

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

Wypróbuj online!

Podobne do odpowiedzi w perlu. (Straciłem swoją bardziej interesującą alternatywę, powinienem je opublikować w ciągu kilku najbliższych godzin).


0

JavaScript (ES6), 103

Obsługuje znaki spoza 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>

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.