Расшифровать строку


41

Это мой первый вызов на PPCG!

вход

Строка, состоящая из двух разных символов ascii. Например

ABAABBAAAAAABBAAABAABBAABA

Вызов

Задача состоит в том, чтобы декодировать эту строку, следуя этим правилам:

  1. Пропустить первые два символа
  2. Разделить оставшуюся часть строки на группы по 8 символов
  3. В каждой группе замените каждый символ, 0если этот символ совпадает с первым символом исходной строки, и с 1другим
  4. Теперь каждая группа представляет байт. Конвертировать каждую группу в символ из байтового кода
  5. Объединить всех персонажей

пример

Давайте расшифруем вышеприведенную строку.

 AB  AABBAAAA  AABBAAAB  AABBAABA
 ^^     ^         ^         ^
 |      |         |         |
 |      \---------|---------/
 |                |
Skip      Convert to binary

Обратите внимание, что Aэто первый символ в исходной строке, а Bвторой. Поэтому замените каждый Aна, 0а каждый Bна 1. Теперь мы получаем:

00110000  00110001  00110010

который находится [0x30, 0x31, 0x32]в двоичном Эти значения представляют символы ["0", "1", "2"]соответственно, поэтому конечный результат должен быть 012.

счет

Это, конечно, , что означает, что ваш код должен быть максимально коротким. Оценка измеряется в байтах.

Ограничения и формат ввода-вывода

Стандартные правила применяются. Вот несколько дополнительных правил:

  • Вы можете принять верный ввод
    • Входная строка состоит ровно из двух разных символов
    • Первые два символа разные
    • Минимальная длина входной строки - 2 символа.
    • Длина всегда даст 2 по модулю 8
  • Вы можете предположить, что строка всегда будет состоять только из печатных символов ASCII
    • Как во входной, так и в декодированной строке
  • В выводе разрешены начальные и конечные пробелы (все, что соответствует /\s*/)

5
Должен сказать, мужик, для первого вызова, это один из лучших форматированных вызовов, которые я когда-либо видел. Как к сведению, песочница сообщества - отличное место для обратной связи перед публикацией, так что вы не получите случайную репутацию за правило, которое вы не знали.
Волшебная Урна Осьминога

@MagicOctopusUrn. Спасибо! Не знал о песочнице, я

2
Я в основном использую его, чтобы люди могли вызывать меня по дублирующим вопросам, очень просто следовать правилам, довольно сложно знать о обманщиках без запоминания мета :). Я бы также порекомендовал проверить чаты, у нас есть чаты почти для каждого языка, на котором вы можете надеяться выучить, и вопросы приветствуются
Волшебная урна осьминога

1
Отличный первый вызов! Еще несколько тестовых случаев были бы опрятными.
Линн

Действительно хороший первый вызов. Было весело играть с этим.
ElPedro

Ответы:


13

брейкфук , 76 71 65 байт

-6 байт благодаря нитродону!

,>>,,[>>++++++++[-[->+<]<<<<[->+>-<<]>>[[-]>>+<<]>[->++<],>>]<.<]

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

Чувствует себя странно, избивая Питона ...


1
Нет, если бы 8 ключевых слов в BF были такими же длинными, как их аналог Python.
user202729

Помогает, что BF автоматически конвертирует юникод.
LastStar007


8

Stax , 15 11 байт

ó║¥U⌂½íèäöñ

Запустите и отладьте его на staxlang.xyz!

Быстрый и грязный подход. Работаем над улучшением. Улучшил это!

Распакованный (13 байт) и пояснения

2:/8/{{[Im:bm
2:/              Split at index 2. Push head, then tail.
   8/            Split into length-8 segments.
     {      m    Map block over each segment:
      {  m         Map block over each character:
       [             Copy first two elements (below) in-place.
        I            Index of character in first two characters.
          :b       Convert from binary.
                 Implicit print as string.

Аааа ... Я знал, что это победит нас.
Волшебная Урна Осьминога

6

JavaScript (Node.js) , 67 байт

s=>s.replace(/./g,x=(c,i)=>(x=x*2|c==s[1],Buffer(i<3|i&7^1?0:[x])))

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

Как?

Мы используем два разных синтаксиса Bufferконструктора:

  • Buffer([n])генерирует буфер, содержащий единственный байт n, и приводится к соответствующему символу ASCII. Рассматриваются только 8 младших значащих битов n .
  • Buffer(n)генерирует буфер из n байтов. Поэтому Buffer(0)генерирует пустой буфер, который приводится к пустой строке.

Примечание: они оба устарели в последних версиях Node. Buffer.from([n])и Buffer.alloc(n)должен использоваться вместо

комментарии

s =>                   // given the input string s
  s.replace(/./g, x =  // initialize x to a non-numeric value (will be coerced to 0)
    (c, i) => (        // for each character c at position i in s:
      x = x * 2 |      //   shift x to the left
          c == s[1],   //   and append the new bit, based on the comparison of c with s[1]
      Buffer(          //   invoke the constructor of Buffer (see above):
        i < 3 |        //     if i is less than 3
        i & 7 ^ 1 ?    //     or i is not congruent to 1 modulo 8:
          0            //       replace c with an empty string
        :              //     else:
          [x]          //       replace c with the ASCII char. whose code is the LSB of x
      )                //   end of Buffer constructor
  ))                   // end of replace(); return the new string

6

bash, 59 58 52 байта

tr -t "$1" 01 <<<$1|cut -c3-|fold -8|sed 'i2i
aP'|dc

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

Спасибо Корову кряку за сохранение 6 байтов.

Эта задача замечательно работает с серией coreutils (и dcдля преобразования и вывода в конце). Во-первых, мы используем

tr -t "$1" 01 <<<$1

транслитерировать два символа на входе в нули и единицы. -tФлаг обрезает первый аргумент длины второго, так что это сводится к транслитерации первые два символа на входе в 0и 1, что это то , что мы хотим. Затем,

cut -c3-

удаляет первые два символа и

fold -8

выводит 8 символов в строке. Наконец, sedкоманда превращает каждую строку во dcфрагмент, который читает число в двоичном виде и выводит этот байт.


Всегда приятно видеть ответ bash :) Вы можете использовать sed, чтобы упростить вычисления постоянного тока, преобразовав каждую строку в код постоянного тока, который печатает каждый символ, и затем оценивая его в dc tio.run/##S0oszvj/… (и пробел после cut -cможет быть удален)
Kritixi Lithos

6

Машинный код Z80 на Amstrad CPC, 32 31 30 байтов

000001  0000  (9000)        ORG &9000
000002  9000  EB            EX DE, HL
000003  9001  46            LD B, (HL)
000004  9002  23            INC HL
000005  9003  5E            LD E, (HL)
000006  9004  23            INC HL
000007  9005  56            LD D, (HL)
000009  9006  1A            LD A, (DE)
000010  9007  05            DEC B
000011  9008  13            INC DE
000012  9009  4F            LD C, A
000014  900A                Light
000015  900A  26 01         LD H, &01
000016  900C                Last
000017  900C  13            INC DE
000018  900D  05            DEC B
000019  900E  C8            RET Z
000021  900F                Loop
000022  900F  1A            LD A, (DE)
000023  9010  B9            CP C
000024  9011  28 01         JR Z, Lable
000025  9013  37            SCF
000026  9014                Lable
000027  9014  ED 6A         ADC HL, HL
000028  9016  30 F4         JR NC, Last
000029  9018  7D            LD A, L
000030  9019  CD 5A BB      CALL &BB5A
000032  901C  18 EC         JR Light

Код принимает инструкцию, заменяющую каждый символ, 0если этот символ совпадает с первым символом исходной строки, и1 буквально с иным способом и никогда не удосуживается проверить, соответствует ли символ второму символу во входной строке. Он просто проверяет, совпадает ли с первым символом и отличается от первого символа.

Я выбежал из регистров (Z80 имеет только 7 легко используемые 8-разрядные регистры, необходимость остальные длинные инструкции) , так что я положил &01в H, наряду с использованием Lзастроить ASCII символов (я просто понял , что это ненужно инициализацию L, сохраняя один байт ). Когда Hпереполняется флаг переноса, символ в Lготов к выводу. К счастью, есть 16-разрядный ADC( Ad d с C arry), который выполняет работу инструкции левого сдвига.

(DE)может быть прочитан, Aхотя (HL)может быть прочитан в любой 8-битный регистр, так что это был компромисс, какой использовать. Я не мог сравнить (DE)с Cнапрямую, поэтому я должен был загрузить один в Aпервый. Метки - это просто случайные слова, которые начинаются с L(требование ассемблера).

  • A Аккумулятор - единственный регистр, который может делать сравнения
  • Bрегистр счетчика для инструкции DJNZ: D ecrement ( B) и J ump, если N на Z ero . Переставив код, я смог выполнить работу DJNZс одним меньшим байтом
  • C первый символ во входной строке
  • D, EА DEадрес текущего входного символа
  • H триггер переноса (каждый 8-й цикл)
  • L выводимый символ создается

введите описание изображения здесь


6

05AB1E , 10 байтов

¦¦Sk8ôJCçJ

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

-3 спасибо эмигне.


Ù             # Unique letters, in order they appear.
 v            # For each...
  yN:         # Push letter and index, replace in input.
     }        # End loop.
      ¦¦      # Remove first x2.
        8ô    # Split into eighths.
          C   # Convert to integer.
           ç  # Convert to char.
            J # Join together entire result.

1
Вы можете использовать 01‡вместо цикла. РЕДАКТИРОВАТЬ: или даже лучше:¦¦Sk8ôJCçJ
Emigna


5

J, 17 13 байт

u:_8#.\2}.1{=

-4 спасибо FrownyFrog

Старая версия:

u:_8#.\2&({.i.}.)

Объяснение:

u:_8#.\2}.1{=
            =  | Self classify, for each unique element x of y, compute x = y, element-wise
          1{   | Second row
       2}.     | Drop 2
  _8#.\        | Convert non-intersecting subarrays of length 8 from binary
u:             | Convert to characters

Примеры:

   = 'ABAABBAAAAAABBAAABAABBAABA'
1 0 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 0 1 1 0 0 1 1 0 1
0 1 0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 1 0 0 1 0

   2}.1{= 'ABAABBAAAAAABBAAABAABBAABA'
0 0 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 0 1 1 0 0 1 0

   _8#.\2}.1{= 'ABAABBAAAAAABBAAABAABBAABA'
48 49 50

   u:_8#.\2}.1{= 'ABAABBAAAAAABBAAABAABBAABA'
012

1
2}.1{=сохранить 4 байта.
FrownyFrog

О, мой, связанный ... Я не могу найти другой байт.
Волшебная Урна Осьминога

1
@MagicOctopusUrn это на самом деле фрагмент, он должен иметь [:в начале :)
FrownyFrog


5

R , 71 байт

function(s)intToUtf8(2^(7:0)%*%matrix((y=utf8ToInt(s))[-1:-2]==y[2],8))

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

Удивительно гольф

Во-первых, преобразует строку в кодовые точки ascii utf8ToInt, сохраняя ее как y. Удаление первых двух символов с отрицательной индексацией короче, чем использование tail.

Массив y[-1:-2]==y[2] эквивалентен битам при применении %*%(умножения матрицы), но сначала мы преобразуем этот массив в matrixwith nrow=8, преобразуя из линейного массива в байтовые группировки. Случайно, мы можем затем преобразовать в кодовые точки ascii, используя умножение матриц с соответствующими степенями 2 2^(7:0), и затем мы конвертируем кодовые точки обратно в строку с intToUtf8.



4

PHP, 73 71 байт

while($s=substr($argn,-6+$i+=8,8))echo~chr(bindec(strtr($s,$argn,10)));

Запустите как трубу с -nRили попробуйте онлайн .

golfings:

  • начать индекс с -6и предварительно увеличить на8
  • эксплойт, который strtrигнорирует чрезмерные символы в длинном параметре (не substrтребуется)
  • перевод 10и затем инвертирование не требуют кавычек -> -1 байт
  • инвертирующий символ вместо кода ASCII -> ~служит границей слова -> -1 байт.

3
По крайней мере, вы должны соответствовать Brainfuck:for(;$s=substr($argn,2+8*$i++,8);)echo~chr(bindec(strtr($s,$argn,10)));
Кристоф

2
@ Christoph Мне нравится, как Brainfuck внезапно становится стандартом для разумной длины ответа.
Нить

4

Pyth, 20 9 байтов

CittxLQQ2

Сохранено 11 байтов благодаря FryAmTheEggman.

Попробуй здесь

объяснение

CittxLQQ2
    xLQQ    Find the index of each character in the string.
  tt        Exclude the first 2.
 i      2   Convert from binary.
C           Get the characters.

@FryAmTheEggman Спасибо. Очевидно, мне еще многое предстоит узнать о Пите.
Мнемоника

Ха-ха, я тоже! Это очень сложный язык игры в гольф. Я надеюсь, что вы продолжите играть в гольф :)
FryAmTheEggman

3

Рубин , 82 79 байт

->s{s[2..-1].tr(s[0,2],'01').chars.each_slice(8).map{|s|s.join.to_i(2).chr}*''}

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


1
Добро пожаловать в PPCG! Я не видел , что там уже был ответ на Ruby , прежде чем я разместил мои, но некоторые типичные приемы игры в гольф применить к вашему подходу тоже - например, последний .joinможет быть заменен *'', и s[0..1]на s[0,2].
Кирилл Л.

3

Japt, 11 байт

¤£bXÃò8 ®Íd

Попытайся


объяснение

¤               :Slice from the 3rd character
 £  Ã           :Map over each X
  bX            :  Get the first 0-based index of X in the input
     ò8         :Split to an array of strings of length 8
        ®       :Map
         Í      :  Convert from base-2 string to base-10 integer
          d     :  Get the character at that codepoint

Очень умное использование s2ярлыка, приятно.
Нить

3

PHP + GNU Multiple Precision, 63 61

<?=gmp_export(gmp_init(substr(strtr($argn,$argn,"01"),2),2));

к сожалению, расширение GMP не активировано по умолчанию (но поставляется).

Запустите так:

echo "ABABABAAAAABABAAAAAABAABBAABAAAABBABAAABBB" | php -F a.php

<?=экономит 2 байта и, возможно, день. ;-)
Тит

@ Да, но, к сожалению, это не работает -R(я пытался).
Кристоф

1
попробуйте -Fвместо этого
Тит


3

Java 8, 143, 142, 141 байт.

s->{char i=47;for(;++i<50;)s=s.replace(s.charAt(i%2),i);for(i=2;i<s.length();)System.out.print((char)Long.parseLong(s.substring(i,i+=8),2));}

-1 байт благодаря @ OlivierGrégoire .

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

Объяснение:

s->{                            // Method with String parameter and no return-type
  char i=47;                    //  Index character, starting at 47
  for(;++i<50;)                 //  Loop 2 times
    s.replace(s.charAt(i%2),i)  //   Replace first characters to 0, second characters to 1
  for(i=2;i<s.length();)        //  Loop `i` from 2 upwards over the String-length
    System.out.print(           //   Print:
     (char)                     //    As character:
      Long.parseLong(           //     Convert Binary-String to number
       s.substring(i,i+=8)      //      The substring in range [i,i+8),
      ,2));}



2

APL + WIN, 30 байтов

Начало индекса 0. Запрашивает ввод строки

⎕av[2⊥¨(+\0=8|⍳⍴b)⊂b←2↓s≠↑s←⎕]

Объяснение:

s≠↑s←⎕ prompts for string and creates binary vector not equal to first character

b←2↓s drops first two elements of binary

(+\0=8|⍳⍴b)⊂ splits binary into groups of 8

2⊥¨ converts each group to decimal

⎕av[...] displays decoded characters

Я предполагаю, что Quad-AV находится в линии с ASCII для APL + WIN?
Захари

@ Zacharý Да для первых 128 символов. Специальные символы APL заменяют некоторые символы в расширенном наборе символов ASCII.
Грэм

2

Красный , 110 байт

func[s][t: 0 i: 128 foreach c next next s[if c = s/2[t: t + i]i: i / 2 if i = 0[prin to-char t t: 0 i: 128]]] 

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

Объяснение:

Простое простое решение, без встроенных функций.

f: func [s] [                      ; s is the argument (string)
    t: 0                           ; total - initially 0
    i: 128                         ; powers of 2, initially 0
    b: s/2                         ; b is the second charachter
    foreach c next next s [        ; for each char in the input string after the 2nd one
        if c = b [t: t + i]        ; if it's equal to b than add the power of 2 to t
        i: i / 2                   ; previous power of 2
        if i = 0 [                 ; if it's 0 
            prin to-char t         ; convert t to character and print it
            t: 0                   ; set t to 0
            i: 128                 ; i to 128
        ]
    ]
] 

2

Google Sheets, 123 байта

=ArrayFormula(Join("",IfError(Char(Bin2Dec(Substitute(Substitute(Mid(A1,3+8*(Row(A:A)-1),8),Left(A1),0),Mid(A1,2,1),1))),""

Вход находится в ячейке A1. Google автоматически добавит )))в конец формулы.

Объяснение:

  • Mid(A1,3+8*(Row(A:A)-1),8) захватывает куски символов по 8 за раз, начиная с третьего.
  • Substitute(Mid(~),Left(A1),0) заменяет каждый экземпляр первого символа на 0
  • Substitute(Substitute(~),Mid(A1,2,1),1) заменяет второй символ 1.
  • Char(Bin2Dec(Substitute(~))) преобразует блок в десятичную, а затем в ASCII.
  • IfError(Char(~,""))исправляет все ошибки, возникающие из-за того, что Row(A:A)возвращает намного больше значений, чем мы, что Bin2Decдает нам множество нулевых значений и Charошибок на нуле.
  • ArrayFormula(Join("",IfError(~)))объединяет все Charрезультаты и ArrayFormulaделает Row(A:A)возвращаемый массив значений вместо только первого значения.

2

Рубин , 61 42 байта

-19 байт благодаря benj2240

->s{[s[2..-1].tr(s[0,2],"01")].pack("B*")}

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


packэто вдохновенный выбор, но сейчас вы как будто идете по длинному пути. Это может сделать еще больше работы для вас.
benj2240

1
Да, это была полная блокировка разума с моей стороны ...
Кирилл Л.



2

Python 2 , 88 байт

i=input()
f=''.join('10'[x==i[0]]for x in i[2:])
while f:print chr(int(f[:8],2));f=f[8:]

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

Не самый короткий - просто альтернативный способ.

Следующая версия печатает вывод в одну строку для 98 байтов, хотя правила утверждают, что конечный пробел разрешен .:

i=input();f=''.join('10'[x==i[0]]for x in i[2:]);o=""
while f:o+=chr(int(f[:8],2));f=f[8:]
print o

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


Окончательный вывод должен быть на одной строке, а не на трех.
idrougge

Из OP: «В выводе разрешены начальные и конечные пробелы (все, что соответствует / \ s * /)». Новые строки совпадений /\s*/.
ElPedro

1
Извините, я недостаточно хорошо разбираюсь в регулярных выражениях. : /
idrougge

Я тоже, но я гуглил это, чтобы быть уверенным ;-)
ElPedro




1

Haskell , 124 105 93 байта

f(x:_:y)=fromEnum.(/=x)<$>y
g[]=[]
g s=(toEnum.sum.zipWith((*).(2^))[7,6..0])s:g(drop 8s)
g.f

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

fпреобразует строку в список битов, сравнивая каждый символ с первым, превращая Bools в нули и единицы с fromEnum. gделит этот список на группы по 8, преобразует их в десятичные и принимает значение результирующего числа как Enum, которое Charявляется экземпляром.

Изменения:

  • -19 байтов благодаря @Laikoni (удаление импорта, встраивание mapв функцию)
  • -12 байт, вдохновленный ответом @ Lynn (избавиться от takeархивирования с более коротким списком)

2
Вы можете использовать toEnumвместо chrи отказаться от импорта. Также mapможет быть включен в g. Пространство между 8 sможет быть удалено.
Лайкони

1

Forth (gforth) , 83 байта

: f over c@ 0 rot 2 do 2* over i 4 pick + c@ <> - i 8 mod 1 = if emit 0 then loop ;

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

Ввод - это стандартная строка Forth (адрес и длина), вывод выводится на стандартный вывод

объяснение

over c@          \ get the value of the first character in the string
0 rot            \ add a starting "byte" value of 0 and put the length on top of the stack
2 do             \ start a loop from 2 to length-1
   2*            \ multiply the current byte value by 2 (shift "bits" left one)
   over          \ copy the reference char to the top of the stack
   i 4 pick +    \ add the index and the starting address to get address of the current char
   c@ <>         \ get the char at the address and check if not equal to the reference char
   -             \ subtract the value from our bit count, -1 is default "true" value in forth
   i 8 mod 1 =   \ check if we are at the last bit in a byte
   if            \ if we are
      emit 0     \ print the character and start our new byte at 0
   then          \ and end the if statement
loop             \ end the loop
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.