Artımlı Şifre


19

Bu görev oldukça basittir ve üç farklı "operatör" karakteri kullanır. Senin görevin, kullanarak kodlamak için aşağıdaki görevi gerçekleştirmek, harflerin basit dizisi verilir <, >, *. Büyük veya küçük harfleri kullanmayı seçebilirsiniz, her ikisini de işlemeniz gerekmez.


Şifre Açıklaması

Şifre basittir, *"gönder" işleviniz olarak , harf 1'den bitiş harfine geçmek için arttırma ve azaltma işlemlerini kullanırsınız . "Artış" operatörü olacak >ve "Artış" olacaktır <.

Kelimesini kullanan bir örnek adbc:

  • Sözcüğün ilk harfiyle başlayın, o harfin çıktısını alın. a
  • Ardından, geçerli harfi bir sonraki harfe "yönlendirmek" için >ve <(beyin gibi) kullanın. mektuba 1 a>yükselterek sonuçlanır . neden olacaktır mektubu düşürücü çünkü (o sarar, her zaman operasyonların AZINDAN sayısında çıkan yönünü seçmelisiniz).aba<z
  • Bir sonraki harfe ulaştığımızı göstermek için doğru minimalize kombinasyonunu <ve >a çıktısını aldıktan sonra *.

Kodlama adımları adbcşöyle olacaktır:

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

Örnekler

Kodlama adımları azaşöyle olacaktır:

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

Daha fazla örnek:

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

kurallar

  • Biz edilir kodlama böylece karışıklık yok yukarı ki çözemez.
  • Mesajın harf [A-Z]veya [a-z]seçim içereceğini varsayabilirsiniz .
  • *(EG $) olarak belirtmek için harf olmayan / sayısal / ayrılmış karakter kullanabilirsiniz .
  • Sonuna sahip olmalısınız *, tekrarlarda örtük değildir.
  • Boş dize olmadığını varsayabilirsiniz, ancak tek bir karakter mümkündür.
  • Sonraki harfe her iki yönde de eşitse, bir yön seçebilirsiniz.
  • Bu , en düşük bayt sayısı kazanır.

Lütfen cevabınızı açıklayın, başkalarının bu şekilde öğrenmesine yardımcı olur.


Açık olmak gerekirse, son test senaryosu abcdefghijklmnopqrstuvwxyzkendi girdisini temsil ediyor ve değil mi?
Nick Clifford

1
@NickClifford evet.
Sihirli Ahtapot Urn

Bence zlkullanmalıyım >.
xnor

4
Örnekleri kontrol edebilir misiniz? alphabetbence a>>>>>>>>>>>*>>>>*<<<<<<<<*<<<<<<<*>*>>>*<<<<<<<<<<<*ve ikinci bir çözüm zlolması gerekir z>>>>>>>>>>>>*ve olması bananagerekirb<*<<<<<<<<<<<<<*>>>>>>>>>>>>>*<<<<<<<<<<<<<*>>>>>>>>>>>>>*
Jörg Hülsermann

@xnor doğru, el ile yazım hatası oldu zm. @jorg iyi yakalar, hepsini düzeltti, manuel bir çabaydı.
Sihirli Ahtapot Urn

Yanıtlar:


2

Jöle , 17 bayt

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

Bunun yerine boşluk karakteri kullanır *(boşluk veya satırsonu bir bayt kaydeder ”*).

İle İşleri ya büyük okunur veya küçük harf okunur girişi.

Çevrimiçi deneyin! ya da bir test takımına bakın(bu boşlukların yerini*okuma kolaylığı sağlamak içindeğiştirin).

Nasıl?

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 makine kodu, 70 68 67 bayt

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

Nasıl çalışır:

            |   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

Bu. Bu çok güzel. Bunu GERÇEKTEN hızlı bir şekilde yaptın, dang.
Sihirli Ahtapot Urn

Teşekkürler. Gerçi hemen hemen önemsiz bir çözüm. 8086'da oldukça kısa oluyor.
user5434231

10

Python 3 , 87 bayt

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

Çevrimiçi deneyin!

Küçük veya büyük harf ile çalışır.

Program r, girdi dizesindeki karakterlerin üzerinde yineleme yaparken çıktı dizesini oluşturur . Önceki karakteri olarak depolar ve yeni karaktere pulaşmak için artan işlemi hesaplar .pc

Karakterler arasındaki aralık ord(c)-ord(p), (ord(c)-ord(p)-13)%26-13modulo 26'yı aralığa götürür [-13..12]. Olumsuz bir sonuç, adım atmanın daha kısa olduğu anlamına gelir ve pozitif bir sonuç da adım atmak anlamına gelir. Bunun , işaretin bir dizesine >veya <işaretine bağlı olması gerekir. Kullanmak absveya koşullu olmak yerine , negatif s*nolduğunda boş dizeyi veren Python'un dize çarpımından yararlanırız n. İfadede '<'*-d+'>'*d, yanlış imzalı kısım katkıda bulunmaz.

Başlangıç ​​durumu, girdinin ilk karakterine ve geri kalanının Python 3'ün ambalajından çıkarılmasıyla bölünmesiyle gerçekleştirilir r,*s=input(). İlk karakter dizeyi ve başlangıçtaki "önceki" karakteri oluşturmaya başlamak için kullanılır.

Bu ambalajı açmak için Python 3'e geçmeyi öneren ovs'a teşekkürler.



3

JavaScript (ES6), 118 109 107 bayt

Giriş dizesi büyük / küçük harfe duyarlı değildir.

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)

Nasıl çalışır

Python'dan farklı olarak, JS modulo operatörü, bölen yerine bölünenle aynı işarete sahip bir sayı döndürür. Ayrıca, JS repeat()yöntemi, boş bir dize döndürmek yerine negatif bir sayı verildiğinde bir hata atar (ve *yine de basit olandan önemli ölçüde daha uzundur ).

Bunlar, bu meydan okuma için oldukça olumsuz davranışlardır. Bu yüzden, matematik hilelerine güvenmektense tam olarak hangi durumda olduğumuzu daha iyi tespit edebiliriz. (Bu, bu tür numaraların mevcut olmadığı anlamına gelmez, daha ziyade onları bulamadım.)

Aşağıda, dmevcut karakter ile bir önceki karakter arasındaki işaretli mesafe olan 4 olası durumu açıklayan bir tablo bulunmaktadır :

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

Test senaryoları


2

PHP, 127 Bayt

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 Bayt

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


2

JavaScript (ES6), 111 103 bayt

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

Başlangıçta ben nhesaplama sırasında @ Arnauld'ın ayar hilesi adapte önce 111 bayt sürdü sürümü, pmuhtemelen syerine başka bir hile olduğunu düşünüyorum nama geç oluyor bu yüzden rahatsız etmeyeceğim .:


2

Haskell (lambdabot), 161 153 bayt

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

Çevrimiçi deneyin!


Açıklama:

-- 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 bayt

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 Anında penceresinden çalıştırın.

Açıklama:

">" Veya "<" n sayısını yineleyen döngü işlevi için basittir; burada n, i ve i + 1 karakter dizesi arasındaki ascii farkıdır.


2

Java 7-, 232 bayt

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

Hemen hemen önemsiz çözüm. Ungolfed ve yorum yaptı:

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 bayt

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

Detaylı Canlı

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
}

Serin çözüm. Aşağıdakileri anlamak daha kolay, ancak 1 bayt daha uzun:#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, ama bu bir kod golf, bu yüzden her zaman bayt sayısını azaltmayı amaçlıyoruz, yine de kodumun nasıl çalıştığı hakkında ayrıntılı bir açıklama ekledim.
Khaled.K

2

JavaScript (ES6), 140 128 129 111 113 bayt

Diğer JS çözümlerine farklı bir yoldan gittim ama çok iyi çalışmadı - işte şu ana kadar:

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>

  • Luke'un ipi tahrip etme önerisi sayesinde 12 bayt tasarruf etti.
  • Örtük bir son baskı karakteri için izin verdiğini düşündüğüm zorluğun yanlış anlaşılmasını gideren 1 bayt eklendi.
  • Luke'un kapsamlı bir yeniden yazımı sayesinde 18 bayt daha kaydetti.
  • Sayılar geçerli yazdırma karakterleri gibi göründüğü için 2 bayt eklendi.

Orijinal, 131 bayt


1
([x,...s])=>x+s.map(...)12 bayt tasarruf sağlar. Sonuna da bir yazdırma karakteri eklemeniz gerektiğini unutmayın. Bunun `1`+1yerine sadece 2 bayta mal olacak bir sayı kullanmanızı öneririm `*`.
Luke

Teşekkürler Luke; Böyle bir dize girdisini yıkabileceğimi unutmuştum. Dün gece bu meydan okumayı yanlış okumalıydım; Bunun son iz karakteri sözü yemin edebilirim oldu örtük. Ne yazık ki, sadece jointek harfli girişler için geçersiz bir çıktı ile sonuçlanır sonra bunu takmak . Ancak, yazdırma karakterini mapyöntem içinde taşımak yalnızca 1 bayt tutar.
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``111 bayt için
Luke

Tekrar teşekkürler, @Luke. Düzenlemeden önce, yukarıdakileri kendi cevabınız olarak göndermeyi tercih eder misiniz? Bunun iyi olması için benimkinden (neredeyse bir melez ve Arnauld'un bir melezi) yeterince farklı olduğunu hissediyorum.
Shaggy

Hayır, bunu düzenleyebilirsin. Bir reduceçözüm bulmaya çalıştım ama 115 bayt olduğu ortaya çıktı.
Luke

2

C ++, 210 190 bayt

Golfte İlk Denemem!

#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 yazdırılacak <,> veya * karakterini saklar. İlk önce dizinin ilk elemanını yazdırır, ardından dizinin ilk ila son elemanı için bir döngü çalıştırır. j, önceki öğeyi saklar ve sonra j, sırasıyla * a'ya yakınsa veya <veya> set k ila <,> olarak karşılaştırılıp karşılaştırılır ve ardından k yazdırılır, ardından j, p'ye eşit oluncaya kadar bu döngüyü çalıştırır. Sonra her ikinci döngüden sonra yazdırın *.


2
Siteye Hoşgeldiniz! Doğru hatırlıyorsam *p!=0ile değiştirilebilir *p. İçindeki alanın char *ada gereksiz olduğundan eminim . Ayrıca bu tam bir cevap yapmak için #include <iostream>ve using namespace std;(sadece eklemek için daha ucuz olabileceğini düşünüyorum std::) gerekir.
Buğday Büyücüsü

2
Siteye Hoşgeldiniz! Sanırım eklemeniz gerekiyor std::ya using namespace std;da muhtemelen #include <iostream>bayt sayınıza da ihtiyacınız olacak.
DJMcMayhem

+1, ancak yukarıda belirtilen iki şeyi düzeltmek, PPCG'ye hoş geldiniz;). Bir şansınız olduğunda TIO Nexus ( tio.run/nexus ) çevresindeki bazı dilleri inceleyin ! Belki kendini Dennis'le tanıştır, o burada yüzen önemli bir adam.
Sihirli Ahtapot Urn

Öneriler ve hataları gösteren herkese teşekkürler. Kodu kısa süre içinde güncelleyeceğim.
0x81915

1

05AB1E , 17 bayt

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

Çevrimiçi deneyin!

açıklama

Kullanımları >, <ve <space>anlamında olabildikleri için artım , eksiltme , teslim

¬                  # 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

Ve bunu 3 saat kaybetti 😉.
Sihirli Ahtapot Urn

1

Haskell , 167 168 126 bayt

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)

Şimdi xnor'ın aritmetik çözümünü kullanıyor. Kodlanacak dizenin e strnerede str :: Stringolduğu ile çağırın .


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.