Зростання шифру


19

Це завдання досить просте і використовує три чіткі "операторські" символи. Ваше завдання, з огляду на просту послідовність літер, виконайте наступне завдання , щоб закодувати його з допомогою <, >, *. Ви можете скористатися великими або малими літерами, не потрібно обробляти обидва.


Пояснення шифру

Шифр простий, ви використовуєте операції з збільшення та зменшення, щоб переходити від літери 1 до кінця букви, *будучи вашою функцією "подати". Оператор для "приросту" буде, >а "декремент" буде <.

Приклад використання слова adbc:

  • Почніть з першої літери слова, виведіть цю букву. a
  • Далі, використовуйте >та <(як brainfuck), щоб "перейти" поточного листа до наступного. a>це призведе до "підвищення" aна 1 лист b. a<це призведе до того, zщо ви опускаєте букву (вона загортає, ви завжди повинні вибирати напрямок, що призводить до ОСТАННЯ кількість операцій).
  • Після виведення правильної мінімізованої комбінації <та >виведення a *позначаємо, що ми дійшли до наступної літери.

Крок для кодування adbc:

a          # a
a>>>*      # ad
a>>>*<<*   # adb
a>>>*<<*>* # adbc

Приклади

Крок для кодування aza:

a       # a
a<*     # az
a<*>*   # aza

Більше прикладів:

"abcdef"    =  "a>*>*>*>*>*"
"zyaf"      =  "z<*>>*>>>>>*"
"zzzzzz"    =  "z*****"
"z"         =  "z"
"zm"        =  "z<<<<<<<<<<<<<*" or "z>>>>>>>>>>>>>*" (equidistant)
"zl"        =  "z>>>>>>>>>>>>*"
"alphabet"  =  "a>>>>>>>>>>>*>>>>*<<<<<<<<*<<<<<<<*>*>>>*<<<<<<<<<<<*"
"banana"    =  "b<*>>>>>>>>>>>>>*<<<<<<<<<<<<<*>>>>>>>>>>>>>*<<<<<<<<<<<<<*" OR "b<*<<<<<<<<<<<<<*>>>>>>>>>>>>>*<<<<<<<<<<<<<*>>>>>>>>>>>>>*"
"abcdefghijklmnopqrstuvwxyz" = "a>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*>*"
"abcdefz"   =  "a>*>*>*>*>*<<<<<<*"

Правила

  • Ми кодуємо не розшифровуючи, тому не псуйте це.
  • Ви можете припустити, що повідомлення буде містити літери [A-Z]або [a-z], на ваш вибір.
  • Для позначення *(EG $) ви можете використовувати будь-який не буквений / цифровий / зарезервований символ .
  • Ви повинні мати закінчення *, воно не вказується на повтори.
  • Ви можете вважати, що немає порожніх рядків, але можливий один символ.
  • Якщо він розташований рівновіддалено до наступної літери, ви можете вибрати напрямок.
  • Це , виграє найменший байт.

Поясніть, будь ласка, свою відповідь, це допомагає іншим навчатися таким чином.


Щоб було зрозуміло, останній тестовий випадок представляє abcdefghijklmnopqrstuvwxyzі не є його власним вкладом?
Нік Кліффорд

1
@NickClifford так.
Magic Octopus Urn

Думаю, zlслід використовувати >.
xnor

4
Чи можете ви, будь ласка, перевірити приклади? alphabetна мій погляд , a>>>>>>>>>>>*>>>>*<<<<<<<<*<<<<<<<*>*>>>*<<<<<<<<<<<*і zlмає бути z>>>>>>>>>>>>*і bananaмає друге рішення існуєb<*<<<<<<<<<<<<<*>>>>>>>>>>>>>*<<<<<<<<<<<<<*>>>>>>>>>>>>>*
Йорг Hülsermann

@xnor вірно, було написано вручну від zm. @jorg хороший улов, виправлений у всіх, було ручним зусиллям.
Чарівний восьминога Урна

Відповіді:


2

Желе , 17 байт

OIżN$ẋ"@€⁾><;€⁶ṭḢ

Використовує пробільний символ замість *(пробіл або новий рядок , зберігає один байт ”*).

Працює з будь-яким прописними тільки або рядковим тільки входом.

Спробуйте в Інтернеті! або перегляньте тестовий набір (там, де ці простори замінено на*легкість читання).

Як?

OIżN$ẋ"@€⁾><;€⁶ṭḢ - Main link: string s          e.g. "adbc"
O                 - cast s to ordinals                [97,100,98,99]
 I                - incremental differences           [3,-2,1]
    $             - last two links as a monad:
   N              -     negate                        [-3,2,-1]
  ż               -     zip together                  [[3,-3],[-2,2],[1,-1]]
         ⁾><      - literal ['>','<']                 "><"
      "@€         - using reversed @arguments for €ach zip with("):
     ẋ            -     repeat (-n are like zeros)    [[">>>",""],["","<<"],[">",""]]
            ;€    - concatenate €ach with:
              ⁶   -     literal ' '                   [[">>>","",' '],["","<<",' '],[">","",' ']]
               ṭ  - tack to:
                Ḣ -     head of s (1st char)          [['a'],[">>>","",' '],["","<<",' '],[">","",' ']]
                  - implicit print   (" not printed:) "a>>> << > "

11

8086 машинного коду, 70 68 67 байт

00000000  be 82 00 bf 43 01 57 31  d2 ac 3c 0d 74 2c 89 d1  |....C.W1..<.t,..|
00000010  88 c2 aa e3 f4 4f 28 c1  9f 88 e7 79 02 f6 d9 83  |.....O(....y....|
00000020  f9 0d 9f 76 05 83 e9 1a  f6 d9 30 fc 9e b0 3c 78  |...v......0...<x|
00000030  02 b0 3e f3 aa b0 2a aa  eb cf c6 05 24 b4 09 5a  |..>...*.....$..Z|
00000040  cd 21 c3                                          |.!.|
00000043

Як це працює:

            |   org 0x100
            |   use16
be 82 00    |       mov si, 0x82        ; source = command line arguments
bf 43 01    |       mov di, result      ; destination = result
57          |       push di
31 d2       |       xor dx, dx          ; clear dx
ac          |   n:  lodsb               ; al = *si++
3c 0d       |       cmp al, 0x0d        ; end of input reached? (newline)
74 2c       |       je q                ; jump to exit in that case
89 d1       |   @@: mov cx, dx          ; store last char in cl
88 c2       |       mov dl, al          ; and store the current char in dl
aa          |       stosb               ; *di++ = al
e3 f4       |       jcxz n              ; skip encoding this char if cx == 0 (only happens for the first char)
4f          |       dec di              ; move di pointer back
28 c1       |       sub cl, al          ; take the difference between this char and the last one
9f          |       lahf                ; store flags from last subtraction in bh
88 e7       |       mov bh, ah
79 02       |       jns @f
f6 d9       |       neg cl              ; make sure cl is positive
83 f9 0d    |   @@: cmp cl, 13          ; which way is shorter?
9f          |       lahf                ; also store these flags
76 05       |       jbe @f
83 e9 1a    |       sub cl, 26          ; invert cl if we're going backwards
f6 d9       |       neg cl
30 fc       |   @@: xor ah, bh          ; xor saved flags together
9e          |       sahf                ; load flags register with the result
b0 3c       |       mov al, '<'
78 02       |       js @f               ; now the sign flag tells us which operator to use
b0 3e       |       mov al, '>'
f3 aa       |   @@: rep stosb           ; while (cx--) *di++ = al
b0 2a       |       mov al, '*'         ; mark the end with an asterisk
aa          |       stosb
eb cf       |       jmp n               ; repeat
c6 05 24    |   q:  mov byte [di], '$'  ; mark end of string
b4 09       |       mov ah, 0x09        ; dos function: print string
5a          |       pop dx              ; dx = string pointer
cd 21       |       int 0x21            ; syscall
c3          |       ret
            |   result rb 0

Це. Це вже не круто. Ви зробили це дійсно швидко, бовтайте.
Magic Octopus Urn

Спасибі. Це майже тривіальне рішення. Просто буває досить короткі 8086.
user5434231

10

Python 3 , 87 байт

r,*s=input();p=r
for c in s:d=(ord(p)-ord(c)-13)%26-13;r+='<'*d+'>'*-d+'*';p=c
print(r)

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

Працює з малої чи великої літери.

Програма будує вихідний рядок у rміру ітерації над символами вхідного рядка. Він зберігає попередній символ як pі обчислює збільшення операції для переходу pдо нового символу c.

Інтервал між символами є ord(c)-ord(p), і (ord(c)-ord(p)-13)%26-13приймає його за модулем 26 до інтервалу [-13..12]. Негативний результат означає, що коротше відступати, а позитивний - означає посилити. Це потрібно перетворити на рядок >або <залежно від знака. Замість того, щоб використовувати absабо умовно, ми використовуємо перевагу множення рядків Python, s*nнадаючи порожній рядок, коли nце від’ємник. У виразі '<'*-d+'>'*dнеправильно підписана частина не сприяє.

Початковий стан обробляється шляхом поділу вхідного сигналу на його перший символ, а решта - при розпакуванні Python 3 r,*s=input(). Початковий символ використовується для початку побудови рядка, а також початкового «попереднього» символу.

Завдяки ovs за те, що вони запропонували перейти на Python 3, щоб зробити це розпакування.


6

Python 3 , 110 93 байт

r,*s=input()
b=r
for a in s:d=(ord(a)-ord(b))%26;r+=['>'*d,'<'*(26-d)][d>13]+'*';b=a
print(r)

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


Ооо ... Працює як для нижнього, так і для верхнього, гарного (але, думаю, ви можете поголити байти, вважаючи той чи інший).
Чарівний восьминіг Урна

Пояснення будь ласка?
Товариш SparklePony

3

JavaScript (ES6), 118 109 107 байт

Вхідний рядок нечутливий до регістру.

s=>s.replace(/./g,(c,i)=>(d=~~s-(s=parseInt(c,36)),i)?'<><>'[k=d/13+2|0].repeat([d+26,-d,d,26-d][k])+'*':c)

Як це працює

На відміну від Python, оператор модуля JS повертає число, що має той самий знак, що і дивіденд, а не дільник. Також repeat()метод JS видає помилку, коли їй надається від'ємне число, а не повертає порожній рядок (і це значно довше, ніж простий у *будь-якому випадку).

Це досить несприятлива поведінка для цього виклику. Отже, нам краще визначити, в якому саме випадку ми, а не покладатися на математичні хитрощі. (Що не означає, що таких хитрощів не існує, а скоріше, що я не зміг їх знайти.)

Нижче наведена таблиця з описом 4 можливих випадків, де dпідписана відстань між поточним символом та попереднім:

d           | floor(d / 13) + 2 | direction | repeat
------------+-------------------+-----------+-------
-25 ... -14 |         0         |     <     | d + 26
-13 ... -1  |         1         |     >     | -d  
 +0 ... +12 |         2         |     <     | +d  
+13 ... +25 |         3         |     >     | 26 - d

Тестові справи



2

JavaScript (ES6), 111 103 байт

f=
s=>s.replace(/./g,(c,i)=>(p=(n+26-(n=parseInt(c,36)))%26,i?'<>'[p+3>>4].repeat(p>13?26-p:p)+'*':c),n=0)
<input oninput=o.textContent=f(this.value)><pre id=o>

s=>[...s].map(c=>(n=parseInt(c,36),p&&(p=(n+26-p)%26,s+='><'[p+3>>4].repeat(p>13?26-p:p)+'*'),p=n),s=s[p=0])&&s

Спочатку версія, яка займала 111 байт, перш ніж я адаптував трюк налаштування @ Арнаульда під nчас обчислень p, я думаю, що, мабуть, є інший трюк, sа замість nцього стає вже пізно, тому я не буду турбуватися:


2

Haskell (лямбдабот), 161 153 байт

w(s:n)=s:(join.snd$mapAccumL(ap(,).g)s n);g c n|q<-[c..'z']++['a'..c],(Just l,s)<-minimum$first(elemIndex n)<$>[(q,'>'),(reverse q,'<')]=(s<$[1..l])++"*"

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


Пояснення:

-- Encode a single letter
g c n | q          <- [c..'z']++['a'..c]        -- The alphabet starting from letter c, looping around
      , (Just l,s) <- minimum                   -- Choose the smallest of ..
                    $ first(elemIndex n)        -- the index of the letter n ..
                  <$> [(q,'>'),(reverse q,'<')] -- from the alphabet q and its reverse

      = (s<$[1..l]) -- Repeat < or > the same number of times as the index of n ..
     ++ "*"         -- and append *

-- Encode the whole string
w (s:n) = s                                -- Yield the first char of the input
        : ( join . snd                     -- Concatinate the result of ..
          $ mapAccumL (\a b->(b,g a b))s n -- executing the g function on each letter of the input string ..
                                           -- except the first, passing the previous letter as the 'c' ..
                                           -- argument on each iteration
          )

2

EXCEL VBA 130 байт

s="":p=Mid(s,1,1):For i=1 To Len(s)-1:b=Asc(Mid(s,i+1,1)):a=Asc(Mid(s,i,1)):p=p &String(abs(b-a),IIf(b>a,">","<"))&"*":Next:[a1]=p

Запустіть його з негайного вікна Excel VBA.

Пояснення:

Просте для циклу, що за допомогою функції String повторює число ">" або "<" n разів, де n - різниця ascii між символами рядка i та i + 1.


2

Java 7-, 232 байти

class C{static void main(String[]a)throws Exception{int i=System.in.read(),j,d,c;p(i);while((j=System.in.read())>10){d=(j-i+26)%26;c=d>13?-1:1;while(d%26>0){d-=c;p(61+c);}p(42);i=j;}}static void p(int k){System.out.print((char)k);}}

Досить тривіальне рішення. Негольфірованний і прокоментував:

class C {
    static void main(String[] a) throws Exception {
        int i = System.in.read(), j, d, c; // i is the last character. j is the current character. d is the difference. c is the direction (-1 is left, 1 is right)
        p(i); // print the starting character first
        while ((j = System.in.read()) > 10) { // keep going until a newline is hit (or an EOF/EOL for -1)
            d = (j - i + 26) % 26; // get the difference (always positive) by wrapping around
            c = d > 13 ? -1 : 1; // get the direction by finding which way is shorter, going right when it's a tie
            while (d % 26 > 0) { // keep going until the current character is reached
                d -= c; // reduce d in the right direction
                p(61 + c); // < is 60 = 61 + (-1), > is 62 = 61 - (-1)
            }
            p(42); // print an asterisk
            i = j; // set the current character to the new reference point
        }
    }

    static void p(int k) {
        System.out.print((char) k);
    }
}

2

C, 170 байт

e(c){putchar(c);}i;m(a,b){i=b-a?a>b?b-a<14?b-a:-(a+26-b):a-b<14?-(a-b):b+26-a:0;while(i>0)e(62),i--;while(i<0)e(60),i++;}f(char*l){e(*l);while(l[1])m(*l,l[1]),e(42),l++;}

Детальний прямий ефір

e(c){ putchar(c); } // encode

g(a,b) // obtain required transition
{
    return (b-a) // calculate distance

         ? (a > b // distance is non-zero

             // if b comes after a
             ? (b-a < 14 // if forward is a shorter path
                 ? b-a // go forward
                 : -(a+26-b)) // otherwise go backward

             // if b comes before a
             : (a-b < 14 // if backward is a shorter path
                 ? -(a-b) // go backward
                 : b+26-a)) // otherwise go forward

         : 0; // if distance is 0
}

// transition
i;m(a,b)
{
    // obtain required transition
    i=g(a,b);

    // encode forward transition
    while(i>0)e('>'), i--;

    // encode backward transition
    while(i<0)e('<'),i++;
}

// incremental cipher function
f(char*l)
{
    e(*l); // encode first character

    while(*(l+1)) // while next character is not END-OF-STRING
        m(*l,*(l+1)), // do transition from current to next character
        e('*'), // encode
        l++; // next
}

Прохолодний розчин. Наступне, мабуть, простіше зрозуміти, але на 1 байт довше:#define x q<14?q:q+26 e(c){putchar(c);}i,q;m(a,b){q=b-a;i=q?(a>b?x:-x):0;while(i>0)e('>'),i--;while(i<0)e('<'),i++;}f(char*l){e(*l);while(*(l+1))m(*l,*(l+1)),e('*'),l++;}
Мореакі

1
@Moreaki Thx, але це код-гольф, тому ми завжди прагнемо зменшити кількість байтів, все одно я додав детальне пояснення того, як працює мій код.
Khaled.K

2

JavaScript (ES6), 140 128 129 111 113 байт

Я пішов іншим маршрутом до інших рішень JS, але це не вийшло дуже добре - ось що я маю досі:

f=

([x,...s])=>x+s.map(y=>`<><>`[r=(d=y[c=`charCodeAt`]()-x[c](x=y))/13+2|0].repeat([d+26,-d,d,26-d][r])+`*`).join``

i.addEventListener("input",()=>o.innerText=i.value&&f(i.value))
console.log(f("adbc"))
console.log(f("aza"))
console.log(f("abcdef"))
console.log(f("zyaf"))
console.log(f("zzzzzz"))
console.log(f("z"))
console.log(f("zm"))
console.log(f("zl"))
console.log(f("alphabet"))
console.log(f("banana"))
console.log(f("abcdefghijklmnopqrstuvwxyz"))
console.log(f("abcdefz"))
<input id=i>
<pre id=o>

  • Збережено 12 байт завдяки пропозиції Луки про руйнування рядка.
  • Додано 1 байт, який виправляє неправильне прочитання виклику, який, на мою думку, дозволив отримати неявний символ остаточного друку.
  • Збережено ще 18 байтів завдяки обширному переписуванню Луки.
  • Додано 2 байти, оскільки, здається, цифри не є дійсними символами друку.

Оригінал, 131 байт


1
([x,...s])=>x+s.map(...)економить 12 байт. Зверніть увагу, що ви також повинні додати символ друку до кінця. Я пропоную використовувати число, яке обійдеться лише в 2 байти `1`+1замість `*`.
Лука

Спасибі, Лука; Я забув, що міг би зруйнувати такий рядок. Я, мабуть, перечитав виклик минулої ночі; Я міг би присягнути, що останній символ друку був неявним. На жаль, просто застосувати його після того, joinяк це призвело б до недійсного виводу для введення однієї літери. Однак переміщення символу друку в межах mapметоду коштувало лише 1 байт.
Кудлатий

1
([x,...s])=>x+s.map(y=>'<><>'[r=(d=y[c='charCodeAt']()-x[c](x=y))/13+2|0].repeat([d+26,-d,d,26-d][r])+0).join``за 111 байт
Лука

Ще раз дякую @Luke. Перш ніж я відредагую це, чи бажаєте ви опублікувати вищезгадане як власну відповідь? Я відчуваю, що він досить відрізняється від мого (майже гібрид його та Arnauld), щоб це було добре.
Кудлатий

Ні, ви можете це відредагувати. Я спробував гольф reduceрішення, але це виявилося 115 байт.
Лука

2

C ++, 210 190 байт

Моя перша спроба в гольфінгу!

#include<iostream>
int g(char*a){char k,j,d;std::cout<<*a;a++;for(;*a;a++){for(j=*(a-1),d=j-*a,k=d>0?d>13?62:60:d<-13?60:62;j!=*a;j+=k-61,j=j<97?122:j>122?97:j)std::cout<<k;std::cout<<'*';}}

k зберігає, який з <,> або * друкувати. Спочатку він просто друкує перший елемент масиву, потім виконує цикл для першого та останнього елемента масиву. j зберігає попередній елемент, а потім порівнюючи, якщо j ближче до * a на <або> встановити k до <,> відповідно, а потім надрукувати k, а потім запустити цю петлю, поки j не стане рівним p. Потім після кожного закінчення друку другого циклу *.


2
Ласкаво просимо на сайт! Якщо я пам'ятаю правильно, *p!=0можна замінити на *p. Я майже впевнений, що місце в ньому char *aтеж непотрібне. Вам також знадобиться #include <iostream>і using namespace std;(хоча я думаю, що це може бути дешевше просто додати std::), щоб зробити це повноцінною відповіддю.
Пшеничний майстер

2
Ласкаво просимо на сайт! Я думаю, що вам потрібно включити std::або, using namespace std;можливо, вам також знадобиться #include <iostream>у вашому підрахунку байтів.
DJMcMayhem

+1, але виправте дві вищезгадані речі, ласкаво просимо до PPCG;). Ознайомтесь з деякими мовами навколо TIO Nexus ( tio.run/nexus ), коли отримаєте можливість! Можливо, познайомтеся з Деннісом, він ключовий хлопець, що пливе тут.
Чарівний Восьминіг Урна

Дякую всім за пропозиції та вказуючи на помилки. Я незабаром оновлю код.
0x81915

1

05AB1E , 17 байт

¬sÇ¥v„<>y0›èyÄ×ðJ

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

Пояснення

Користі >, <і <space>для позначення збільшення , декремента , уявити

¬                  # get the first letter of the input string
 sǥ               # push a list of delta's of the character codes in the input string
    v              # for each delta
     „<>           # push the string "<>"
        y0›        # check if the delta is positive
           è       # use this to index into the string
            yÄ×    # repeat it abs(delta) times
               ðJ  # join to string with a space

І втратив цю на 3 години 😉.
Чарівний восьминіг Урна

1

Haskell , 167 168 126 байт

f=fromEnum
r=replicate
a?b=mod(f a-f b-13)26-13
c#x=r(c?x)'<'++r(-c?x)'>'
s(c,s)x=(x,s++c#x++"*")
e(x:y)=x:snd(foldl s(x,[])y)

Тепер використовується арифметичне рішення xnor. Зателефонуйте, e strде str :: Stringзнаходиться рядок для кодування.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.