Случай перестановки


27

Кому нужно сравнивать вещи без учета регистра, когда вы можете генерировать каждую перестановку прописных и строчных букв? Ни один. Никто! Это ответ. Никто не делает. Ваша задача - достичь этого подвига; генерировать все возможные перестановки прописных / строчных букв для заданного ввода.

вход

Строка печатных стандартных символов ascii. Не следует предполагать, что ввод вводится только строчными буквами. На входе всегда будет хотя бы один символ.

Выход

Каждая перестановка прописных и строчных букв для введенной строки (без дубликатов). Это должно только изменить символы с маленькой и большой версией (числа останутся прежними). Каждая перестановка должна быть выведена в виде строки или списка символов; списки одиночных строк не допускаются.

Примеры

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

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

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

счет

Это , поэтому выигрывает самый короткий ответ (в байтах).

В качестве забавного дополнения посмотрите, сколько дополнительных усилий потребуется для обработки расширенных символов ascii, вот дополнительный тестовый пример:

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

(ваша программа не нуждается в поддержке этого)


10
Интересный тестовый пример Unicode: Σ['Σ', 'σ', 'ς']
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

Можем ли мы использовать список символов вместо строки? Например, если бы Hi!дал, {('H', 'i', '!'), ('h', 'I', '!'), ('h', 'i', '!'), ('H', 'I', '!')}было бы это приемлемо?
DJMcMayhem

@DrGreenEggsandHamDJ Список символов разрешен по умолчанию . В Python это строки-одиночки, которые отличаются.
Деннис

1
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ еще более интересно то, что Σэто заглавная версия в начале слова, σстрочная версия в начале или в середине, но не в конце слова, и ςстрочная версия только в конце слова.
FantaC

1
@DomHastings Как у вас есть список, и вы просто ограничиваете вывод? Это кажется разумным для меня.
тыкай

Ответы:


11

Pyth, 13 12 11

{msrVQd^U2l

1 байт благодаря Leaky Nun!

Еще один байт благодаря Якубе!

Попробуйте здесь или запустите Test Suite

Мы создаем список значений True / False списков, беря декартово произведение списка [0, 1]само по себе количество раз, равное длине входной строки. Таким образом, каждый из подсписков имеет ту же длину, что и входная строка. Затем мы применяем rфункцию как векторную операцию над входом и списком, поэтому мы получаем r letter valueдля каждого подэлемента. rсо вторым аргументом ноль - в нижнем регистре, а с одним - в верхнем. Это создает дубликаты для не-букв, что означает, что нам нужно удалить дубликаты из результата.



@LeakyNun Ах, я пробовал это, но по некоторым причинам я думал, что использую Mна обоих, sи .nбыл той же самой длины. Кажется, я хорошо умею считать. Во всяком случае, редактирование сейчас, спасибо!
FryAmTheEggman

Да, они одинаковой длины, я только что изменил последнюю часть
Leaky Nun

{msrVQd^U2lнемного короче.
Якуб

@Jakube Спасибо! Использование Vдовольно подлый, я не думаю, что когда-либо думал бы об этом здесь.
FryAmTheEggman

8

Желе , 6 байт

żŒsŒpQ

Это монадическая ссылка (функция), которая ожидает строку в качестве левого аргумента и возвращает список строк.

Обрабатывает не-ASCII символы. Попробуйте онлайн!

Как это работает

żŒ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
Получить рект другие языки: р
Аднан

2
Даже после просмотра кодовой страницы меня поражает тот факт, что я постоянно вижу Jelly с самым низким количеством байтов в задачах код-гольфа.
Тыкай

5

Python, 74 71 байт

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

Обрабатывает не-ASCII символы. Проверьте это на Ideone .


5

Oracle SQL 11.2, 276 байт

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

Ужасно, черт возьми, должно быть больше в гольф.


4

05AB1E, 17 байт

Код:

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

Разъяснение:

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

Попробуйте онлайн


4

Брахилог , 25 22 байта

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

Это работает так же, как и строчные / прописные предикаты Prolog, поэтому оно работает и с не-ASCII-буквами:

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

объяснение

В отличие от всех других ответов, которые я публикую на данный момент, здесь не используется подход декартовых произведений.

  • Главный предикат

    :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
    
  • Предикат 1

Это используется для применения верхнего или нижнего регистра к каждому символу ввода, таким образом вычисляя одну возможную перестановку. Использование findall для этого предиката в основном предикате позволяет вычислить все возможные перестановки (с некоторыми дубликатами).

    :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
  • Предикат 2

Это используется для преобразования символа строки в верхний или нижний регистр.

    @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 байт

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

Попробуйте онлайн!

Изменить: @Angs сохранено 11 байтов. Благодарность!


mapM(\x->toLower x:[toUpper x|isAlpha x])должен избавиться от другого импорта?
Ангс

3

MATL , 13 байт

tYov!Z}N$Z*Xu

Попробуйте онлайн!

объяснение

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 байт

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

Редактировать: Сохранено 2 байта, потому что new Setбудут счастливо извлекать уникальные символы из строки.


Когда !c sэто []так, вы можете вернуться [s]вместо этого
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 байт

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

Попытайся

Объяснение:

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

Тест:

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

Вы можете сохранить байт, я думаю: {[X~] '',|.comb.map:{unique .lc,.uc}}(убрать пробел после map:)
Конор О'Брайен,


2

Python, 69 байт

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

Это возвращает кортежи одиночных строк вместо строк. Я не уверен, разрешено ли это.
Деннис

Сохраните 1 байт, используя from itertools import*;и опускаяi.
Byte Commander

OP сказал, что одиночные строки не допускаются. Вы должны обновить этот ответ.
DJMcMayhem

Требование к выходу неоднозначно (все еще есть). После того, как я это опубликовал, ФП пояснил в комментариях. Должен ли я просто удалить этот ответ? Какой протокол правильный?
RootTwo

2

На самом деле, 28 байт

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

Попробуйте онлайн!

Эта программа может обрабатывать символы не ASCII, благодаря волшебству Python 3.

Объяснение:

;╗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 байта

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

Безголовая версия:

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

   } 
}

Объяснение:

  • Принять строку символов, преобразовать строку в нижний регистр.
  • Объявите массив целых чисел, равный длине строки. Заполните его нулями.
  • Храните числа от 0 до 2^strlen(s)в двоичном виде вint массиве (для 3-байтовой строки: 000,001,010 ... 111)
  • В зависимости от того, установлен ли бит в позиции или, переключите регистр.
  • Выведите строку для каждой возможной комбинации.

Попробуйте онлайн!


Когда я впервые делал это в vb6, как 10 лет назад, я полагал, что мое решение было похоже на это. Вы вернули некоторые воспоминания;)
Poke

@Poke Рад, что я мог! :)
Абель Том

Некоторые вещи для игры в гольф: Снимите i++петли для петель и используйте их ++напрямую, а также поместите некоторые детали внутри петли для петель, чтобы по возможности снять кронштейны и полуколонны. Кроме того, вы можете удалить пробел в параметре и использовать троичное-if-назначение в конце. Всего: 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 байт / 232 байт )
Кевин Круйссен

1

Хун , 242 байта

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

Я не уверен, насколько меньше это может быть, к сожалению.

Сначала мы устанавливаем lравным список с 2 ^ (длина t) повторений t. У Hoon нет facфункции в stdlib, но 2 ^ n всегда больше, чем n !, поэтому мы просто отображаем большой список и используемset (hashmap) для дупликации записей.

Затем мы свернем список [0 .. (длина l)], накапливаясь в a (set tape). Нам нужно сделать это вместо lпрямого отображения, потому что нам также нужно знать, какое это повторение чисел ( a), но мы не можем просто увеличить накопитель из-за того, что Hoon является чистым языком.

Мы отображаем [0 .. (длина t)] (опять же, чтобы у нас был текущий индекс), устанавливая tn-й символ в строке, проверяя, является ли n-й до свидания, aи инвертируя регистр (cuss или cass, в зависимости от того, изменяется ли он или не). Тип возврата этой карты - tape.

Затем мы помещаем строку в нашу hashmap и возвращаем hashmap всех строк.


«2 ^ n всегда больше, чем n!». На самом деле n! > 2^n, при условии, что nпо крайней мере 4. (Докажите по индукции, с базовым случаем n=4.) En.wikipedia.org/wiki/...
mathmandan

1

C 216 байт

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

Это другой подход , такой же подход, как и другой ответ C.

Я должен удалить это, и поместить это под другим ответом как комментарий?

Позвольте мне объяснить с 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 байт

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

Опоздал на вечеринку, но все-таки пошел. Спасибо DLosc за напоминание о том, что я пропустил, что дает мне советы по игре в гольф и экономит кучу байтов. :)


@DLosc Спасибо за советы! Я добавлю эти функции в. :)
Блоки

Спасибо за советы. Это действительно помогло. Хотя если я использую {} вместо set (), цикл проходит через набор вместо продуктов (надеюсь, это имеет смысл). По крайней мере, в моей реализации (я использую QPython на Android), {} просто помещает список в набор вместо его преобразования в набор.
Блоки

Я пробовал оба способа, и выполнение {* expr} дает мне SyntaxError.
Блоки

Аааа. Поэтому. Последняя версия QPython на 3.3 или около того.
Блоки

Вот и вы: попробуйте онлайн! (Также исправлена ​​ошибка и игра в гольф.)
DLosc



1

Tcl, 165 181 байт

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

Улучшения благодаря sergiol . Предыдущий ответ:

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}

Использует двоичное число для выбора между верхним / нижним регистром при создании выходного текста.



@sergiol Это достаточно отличается от моего, что вы должны опубликовать его в качестве своего собственного ответа и получить хорошую репутацию за то, что вы круты.
Dúthomhas

Нет. Я изменил только незначительные части вашего ответа, я не изменил ни подход, ни основную алгоритмику, поэтому, с моей точки зрения, я подумал, что не заслуживаю создания нового ответа из вашего! И я сомневаюсь, что смог бы получить алгоритм, краткий вашему оригиналу, для той же цели!
sergiol



0

JavaScript (ES6), 103

Обрабатывает не-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]

Тест

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>

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.