Cipher tambahan

19

Tugas ini agak sederhana, dan menggunakan tiga karakter "operator" yang berbeda. Tugas Anda adalah, diberikan urutan sederhana huruf, melakukan tugas berikut untuk mengkodekan menggunakan <, >, *. Anda dapat memilih untuk menggunakan huruf besar atau kecil, Anda tidak harus menangani keduanya.


Penjelasan Cipher

Sandi sederhana, Anda menggunakan operasi kenaikan dan penurunan untuk melintasi dari huruf 1 ke huruf akhir, dengan *menjadi fungsi "kirim" Anda. Operator untuk "kenaikan" akan >dan "penurunan" akan <.

Contoh menggunakan kata adbc:

  • Mulailah dengan huruf pertama dari kata itu, tuliskan huruf itu. a
  • Selanjutnya, gunakan >dan <(seperti brainfuck) untuk "menavigasi" surat saat ini ke yang berikutnya. a>akan menghasilkan 'membesarkan' aoleh 1 ke surat itu b. a<akan menghasilkan zkarena Anda menurunkan surat (itu membungkus, Anda harus selalu memilih arah yang menghasilkan jumlah operasi TERAKHIR).
  • Setelah mengeluarkan kombinasi minimal yang benar dari <dan >keluaran a *untuk menyatakan bahwa kami telah mencapai huruf berikutnya.

Langkah-langkah untuk menyandikan adbcadalah:

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

Contohnya

Langkah-langkah untuk menyandikan azaadalah:

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

Lebih banyak contoh:

"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>*>*>*>*>*<<<<<<*"

Aturan

  • Kami sedang meng - encode bukan decoding, jadi jangan mengacaukannya.
  • Anda mungkin menganggap pesan itu akan berisi surat [A-Z]atau [a-z], pilihan Anda.
  • Anda dapat menggunakan karakter non-huruf / numerik / cadangan untuk menunjukkan *(EG $).
  • Anda harus memiliki akhir *, itu tidak tersirat pada pengulangan.
  • Anda mungkin menganggap tidak ada string kosong, tetapi satu karakter dimungkinkan.
  • Jika sama jauhnya dari huruf berikutnya, Anda dapat memilih arah.
  • Ini adalah , kemenangan byte-count terendah.

Tolong jelaskan jawaban Anda, ini membantu orang lain belajar dengan cara ini.

Guci Gurita Ajaib
sumber
Untuk memperjelas, test case terakhir mewakili abcdefghijklmnopqrstuvwxyzdan bukan inputnya sendiri?
Nick Clifford
1
@NickClifford ya.
Magic Gurita Guci
Saya pikir zlharus digunakan >.
xnor
4
Bisakah Anda memeriksa contohnya? alphabetmenurut saya a>>>>>>>>>>>*>>>>*<<<<<<<<*<<<<<<<*>*>>>*<<<<<<<<<<<*dan zlseharusnya z>>>>>>>>>>>>*dan untuk bananasolusi kedua adab<*<<<<<<<<<<<<<*>>>>>>>>>>>>>*<<<<<<<<<<<<<*>>>>>>>>>>>>>*
Jörg Hülsermann
@ xnor benar, adalah kesalahan ketik manual zm. @ jorg tangkapan bagus, memperbaiki semuanya, adalah upaya manual.
Magic Gurita Guci

Jawaban:

2

Jelly , 17 byte

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

Menggunakan karakter spasi sebagai ganti *(spasi ,, atau baris baru ,, menyimpan satu byte lebih ”*).

Pekerjaan dengan baik huruf besar-satunya atau masukan huruf kecil saja.

Cobalah online! atau lihat test suite (di mana ruang-ruang tersebut diganti dengan*untuk memudahkan membaca).

Bagaimana?

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>>> << > "
Jonathan Allan
sumber
11

8086 kode mesin, 70 68 67 byte

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

Bagaimana itu bekerja:

            |   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
pengguna5434231
sumber
Ini. Ini sangat keren. Anda melakukan ini BENAR-BENAR cepat juga, sial.
Magic Gurita Guci
Terima kasih. Ini cukup banyak solusi sepele sekalipun. Kebetulan cukup singkat di 8086.
user5434231
10

Python 3 , 87 byte

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

Cobalah online!

Bekerja dengan huruf kecil atau besar.

Program membangun string keluaran rsaat ia mengulangi karakter dalam string input. Ini menyimpan karakter sebelumnya sebagai p, dan menghitung operasi tambahan untuk mendapatkan dari pke karakter baru c.

Interval antara karakter adalah ord(c)-ord(p), dan (ord(c)-ord(p)-13)%26-13membawanya modulo 26 ke interval [-13..12]. Hasil negatif berarti lebih pendek untuk mundur, dan hasil positif berarti naik. Ini perlu dikonversi ke string >atau <tergantung pada tanda. Daripada menggunakan absatau kondisional, kami mengambil keuntungan dari penggandaan string Python s*nmemberikan string kosong ketika nnegatif. Dalam ungkapan '<'*-d+'>'*d, bagian yang salah ditandatangani tidak berkontribusi.

Keadaan awal ditangani dengan memisahkan input menjadi karakter pertama dan sisanya dengan membongkar Python 3 r,*s=input(). Karakter awal digunakan untuk mulai membangun string, serta karakter awal "sebelumnya".

Terima kasih kepada OVS untuk menyarankan beralih ke Python 3 untuk melakukan membongkar ini.

Tidak
sumber
6

Python 3 , 110 93 byte

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)

Cobalah online!

ovs
sumber
Ooo ... Berfungsi untuk huruf kecil dan besar, bagus (tapi saya pikir Anda bisa memotong byte dengan mengasumsikan satu atau yang lain).
Guci Gurita Sihir
Penjelasannya tolong?
Kamerad SparklePony
3

JavaScript (ES6), 118 109 107 byte

String input tidak peka huruf besar-kecil.

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)

Bagaimana itu bekerja

Tidak seperti Python, operator modulo JS mengembalikan nomor yang memiliki tanda sama dengan dividen daripada pembagi. Juga, repeat()metode JS melempar kesalahan ketika diberi angka negatif, daripada mengembalikan string kosong (dan itu secara signifikan lebih lama dari pada yang sederhana *).

Ini adalah perilaku yang agak tidak menguntungkan untuk tantangan ini. Jadi, sebaiknya kita mengidentifikasi dalam kasus yang tepat kita daripada mengandalkan trik matematika. (Yang tidak berarti bahwa trik semacam itu tidak ada, tetapi aku gagal menemukannya.)

Di bawah ini adalah tabel yang menggambarkan 4 kasus yang memungkinkan, di mana djarak yang ditandatangani antara karakter saat ini dan yang sebelumnya:

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

Uji kasus

Arnauld
sumber
2

PHP, 127 Bytes

for($l=ord($r=($s=$argn)[0]);$x=ord($s[++$i]);$l=$x)$r.=str_pad("",($a=abs($n=$l-$x))<14?$a:26-$a,"><"[$n>0^$a>13])."*";echo$r;

Testcases

PHP, 137 Bytes

for($l=$r=($s=$argn)[0];$s[++$i];$l=$s[$i])$r.=str_pad("",$d=min($a=abs(ord($l)-ord($s[$i])),$b=26-$a),"><"[$d<$b^$l<$s[$i]])."*";echo$r;

Testcases

Jörg Hülsermann
sumber
2

JavaScript (ES6), 111 103 byte

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

Awalnya versi yang mengambil 111 byte sebelum saya mengadaptasi trik pengaturan Arnauld @ nsaat komputasi p, saya pikir mungkin ada trik lain menggunakan sbukan ntapi sudah terlambat jadi saya tidak akan repot .:

Neil
sumber
2

Haskell (lambdabot), 161 153 byte

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])++"*"

Cobalah online!


Penjelasan:

-- 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
          )
BlackCap
sumber
2

EXCEL VBA 130 byte

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

Jalankan dari jendela Excel VBA Immediate.

Penjelasan:

Sederhana untuk loop yang dengan fungsi String untuk mengulangi ">" atau "<" n berapa kali n adalah perbedaan ascii antara string karakter i dan i + 1.

Rohan
sumber
2

Java 7-, 232 byte

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

Cukup banyak solusi sepele. Tidak dikumpulkan dan berkomentar:

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);
    }
}
HyperNeutrino
sumber
2

C, 170 byte

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

Detil Live

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
}
Khaled.K
sumber
Solusi keren Berikut ini mungkin lebih mudah dipahami, tetapi 1 byte lebih lama:#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++;}
Moreaki
1
@Moreaki Thx, tapi ini kode-golf, jadi kami selalu berusaha mengurangi jumlah byte, toh saya telah menambahkan penjelasan terperinci tentang cara kerja kode saya.
Khaled.K
2

JavaScript (ES6), 140 128 129 111 113 byte

Saya menempuh rute berbeda ke solusi JS lainnya tetapi tidak berhasil dengan baik - inilah yang saya miliki sejauh ini:

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>

  • Menyimpan 12 byte berkat saran dari Luke tentang perusakan string.
  • Ditambahkan 1 byte memperbaiki kesalahan membaca tantangan, yang saya pikir diperbolehkan untuk karakter cetak akhir implisit.
  • Menyimpan 18 byte lagi berkat penulisan ulang yang ekstensif oleh Luke.
  • Menambahkan 2 byte karena tampaknya angka bukan karakter cetak yang valid.

Asli, 131 byte

Shaggy
sumber
1
([x,...s])=>x+s.map(...)menghemat 12 byte. Perhatikan bahwa Anda juga harus menambahkan karakter cetak hingga akhir. Saya sarankan menggunakan nomor, yang hanya akan dikenakan biaya 2 byte `1`+1bukan `*`.
Luke
Terima kasih, Luke; Saya lupa saya bisa merusak input string seperti itu. Saya pasti salah membaca tantangan tadi malam; Saya berani bersumpah itu mengatakan karakter cetak terakhir adalah implisit. Sayangnya, hanya memasangnya setelah joinakan menghasilkan output yang tidak valid untuk input satu huruf. Namun, memindahkan karakter cetak dalam mapmetode hanya biaya 1 byte.
Shaggy
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``for 111 bytes
Luke
Sekali lagi terima kasih, @Luke. Sebelum saya mengeditnya, apakah Anda lebih suka memposting di atas sebagai jawaban Anda sendiri? Saya merasa itu cukup berbeda dari milik saya (hampir merupakan hibrida dan milik Arnauld) sehingga tidak masalah.
Shaggy
Nah, Anda bisa mengeditnya. Saya mencoba golf reducesolusi, tapi itu ternyata 115 byte.
Luke
2

C ++, 210 190 byte

Coba Pertama Saya Di Golf!

#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 menyimpan yang mana dari <,> atau * untuk dicetak. Pada awalnya ia hanya mencetak elemen pertama dari array kemudian menjalankan satu loop untuk dari pertama ke elemen terakhir dari array. j menyimpan elemen sebelumnya dan kemudian dengan membandingkan jika j lebih dekat ke * a dengan <atau> set k ke <,> masing-masing dan kemudian cetak k kemudian jalankan loop ini sampai j menjadi sama dengan p. Kemudian setelah setiap akhir cetak lingkaran kedua *.

0x81915
sumber
2
Selamat datang di situs ini! Jika saya ingat dengan benar *p!=0bisa diganti dengan *p. Saya cukup yakin ruang dalam char *ajuga tidak perlu. Anda juga perlu melakukannya#include <iostream> dan using namespace std;(walaupun saya pikir mungkin lebih murah untuk hanya menambahkan std::) untuk membuat ini jawaban yang lengkap.
Wheat Wizard
2
Selamat datang di situs ini! Saya pikir Anda perlu memasukkan std::atau using namespace std;Anda mungkin juga perlu #include <iostream>dalam hitungan byte Anda.
DJMcMayhem
+1, tetapi perbaiki dua hal yang disebutkan di atas, selamat datang di PPCG;). Lihat beberapa bahasa di sekitar TIO Nexus ( tio.run/nexus ) saat Anda mendapat kesempatan! Mungkin memperkenalkan dirimu pada Dennis, dia adalah kuncinya di sekitar sini.
Magic Gurita Guci
Terima kasih semuanya atas saran dan menunjukkan kesalahannya. Saya akan segera memperbarui kode.
0x81915
1

05AB1E , 17 byte

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

Cobalah online!

Penjelasan

Penggunaan >, <dan <space>untuk menunjukkan kenaikan , penurunan , kirim

¬                  # 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
Emigna
sumber
Dan kehilangan ini satu per 3 jam 😉.
Magic Gurita Guci
1

Haskell , 167 168 126 byte

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)

Sekarang menggunakan solusi aritmatika xnor. Panggil dengan e strmana str :: Stringstring yang akan dikodekan.

Julian Wolf
sumber
1

Haskell , 109 byte

a#b=mod(a-b-13)26-13
r=replicate
h(a:b:s)=r(a#b)'>'++r(-a#b)'<'++'*':h(b:s)
h e=""
f(a:r)=a:h(fromEnum<$>a:r)

Cobalah online! Menggunakan pendekatan xnor . Panggil dengan f "somestring".

Laikoni
sumber