增量密码


19

此任务非常简单,并使用了三个不同的“操作员”字符。你的任务是,给定的字母简单的顺序,请执行以下任务使用对它进行编码<>*。您可以选择使用大写或小写字母,而不必同时使用两者。


密码说明

密码很简单,您使用递增和递减运算从字母1到结尾字母移动, *具有“提交”功能。“增加”的运算符为>,“减少” 的运算符为<

一个使用单词的例子adbc

  • 从单词的第一个字母开始,输出该字母。 a
  • 接下来,使用><(例如Brainfuck)将当前字母“导航”到下一个字母。a>将导致a该字母“ 加1” ba<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是的。
魔术章鱼缸

我认为zl应该使用>
xnor

4
您能否检查示例?alphabet在我看来a>>>>>>>>>>>*>>>>*<<<<<<<<*<<<<<<<*>*>>>*<<<<<<<<<<<*,并zlz>>>>>>>>>>>>*banana应该在第二个解决方案存在b<*<<<<<<<<<<<<<*>>>>>>>>>>>>>*<<<<<<<<<<<<<*>>>>>>>>>>>>>*
约尔格Hülsermann

@xnor正确,是来自的手动错字zm。@jorg的好渔获物,固定了所有这些,是手工完成的。
Magic Octopus Urn

Answers:


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

这个。这太酷了。你也真的很快做到了
魔术八达通

谢谢。不过,这几乎是微不足道的解决方案。恰好是相当短的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的unpacking)来处理初始状态r,*s=input()。初始字符用于开始构建字符串,以及初始的“上一个”字符。

感谢ovs建议切换到Python 3进行解压缩。



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

PHP,127字节

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;

测试用例

PHP,137字节

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;

测试用例


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个字节,然后我才使用@Arnauld的设置技巧进行n计算p,我认为可能还有另一个技巧可以使用s代替,n但它来晚了,所以我不会打扰。


2

的Haskell(lambdabot),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立即窗口运行它。

说明:

简单的for循环,使用String函数可以重复“>”或“ <” n次,其中n是i和i + 1字符串之间的ASCII差。


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++;}
Moreaki '17

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>

  • 由于Luke提出了有关破坏字符串的建议,因此节省了12个字节。
  • 增加了1个字节,以解决对挑战的误读,我认为这允许隐式最终印刷字符。
  • 由于Luke进行了广泛的重写,因此又节省了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存储要打印的<,>或*。首先,它仅打印array的第一个元素,然后对array的从第一个元素到最后一个元素运行循环。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)!也许向您介绍丹尼斯,他是周围的重要人物。
魔术八达通Ur

感谢大家的建议并指出错误。我将很快更新代码。
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小时😉。
魔术八达通n

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要编码的字符串。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.