Розшифруйте рядок


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.

Оцінка балів

Це, звичайно, , що означає зробити свій код якомога коротшим. Оцінка вимірюється в байтах.

Обмеження та формат IO

Діють стандартні правила. Ось кілька додаткових правил:

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

5
Треба сказати, людина, для першого виклику, це один із кращого форматування, який я коли-небудь бачив. Як фій, пісочниця спільноти є прекрасним місцем для зворотного зв’язку перед публікацією, щоб ви не випадково не бомбили за правило, якого ви не знали.
Чарівна Восьминіжка Урна

@MagicOctopusUrn. Дякую! Не знав про пісочницю, я

2
Я в основному використовую його, щоб люди могли викликати мене на дублюючі запитання, дуже прості в дотриманні правил, досить важко знати про дупи без запам'ятовування мета :). Я також рекомендую перевірити кімнати чату, у нас є чати майже на кожній мові, яку ви можете сподіватися вивчити, і питання заохочуються.
Magic Octopus Urn

1
Чудовий перший виклик! Ще кілька тестових випадків були б акуратними.
Лінн

Дійсно приємний перший виклик. Було весело грати з цим.
ElPedro

Відповіді:


13

мозковий ебать , 76 71 65 байт

-6 байт завдяки Nitrodon!

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

Спробуйте в Інтернеті!

Відчувається дивне побиття Python ...


1
Не якби 8 ключових слів у BF були такими ж, як їх аналог Python.
користувач202729

Це допомагає BF автоматично перетворювати unicode.
LastStar007


8

Стакс , 15 11 байт

ó║¥U⌂½íèäöñ

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

Швидкий 'n' брудний підхід. Робота над її вдосконаленням. Покращили його!

Розпаковано (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)створює порожній буфер, який примусовий до порожнього рядка.

Примітка. Вони є застарілими в останніх версіях вузла. 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 байт.

Цей виклик надзвичайно добре спрацьовує з низкою основних ядер (і dcперетворення та вихід у кінці). Спочатку ми використовуємо

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

транслітерація двох символів вхідних даних до нулів та одиниць. -tПрапор обрізає перший аргумент довжини другого, так що це зводиться до транслітерації перші два символи на вході в 0і 1, що це те , що ми хочемо. Тоді,

cut -c3-

видаляє перші два символи та

fold -8

виводить 8 символів на рядок. Нарешті, sedкоманда перетворює кожен рядок у dcфрагмент, який читає число як бінарне та виводить цей байт.


Завжди приємно бачити відповідь bash :) Ви можете використовувати sed для спрощення розрахунків dc, перетворюючи кожен рядок у код dc, який виводить кожен символ, а потім eval'ing в dc tio.run/##S0oszvj/… (і простір після cut -cможна буде видалити)
Kritixi Lithos

6

Код машини Z80 на CPC Amstrad, 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переповнюється прапор Carry, символ у 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 завдяки emigna.


Ù             # 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‡замість циклу. EDIT: або ще краще:¦¦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]еквівалентний бітам, коли застосовується %*%(множення матриці), але спочатку ми переформатуємо цей масив у matrixс 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або спробуйте в Інтернеті .

гольф:

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

3
Принаймні, ви повинні відповідати мозкові: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 Дякую Очевидно, що я ще маю багато дізнатися про Pyth.
Мнемонічне

Ха-ха, і я! Це дуже хитра мова про гольф. Сподіваюся, ви продовжите гольф в ньому :)
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! Я не бачив, щоб у Рубі вже була відповідь, перш ніж я розмістив шахту, але деякі типові прийоми з гольфу застосовуються і до вашого підходу - наприклад, останній .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 Множинна точність, 63 61

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

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

Бігайте так:

echo "ABABABAAAAABABAAAAAABAABBAABAAAABBABAAABBB" | php -F a.php

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

@Titus так, але, на жаль, це не працює -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ý

@ 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 Таблиці, 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

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

З ОП: "Провідні та остаточні пробіли дозволені у висновку (все, що відповідає / \ 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, перетворює їх у десяткові та приймає значення отриманого числа як an Enum, що Charє екземпляром.

Зміни:

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

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

1

Четвертий (gforth) , 83 байти

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

Спробуйте в Інтернеті!

Введення - це стандартний рядок четвертого рядка (адреса та довжина), що друкується у stdout

Пояснення

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.