通过循环三进制数字来混淆文本


28

挑战的目标是编写最短的函数/程序以获取输入文本,使用以下方法对其进行加密,然后返回结果。

作为示例,我将使用字符串hello world

首先,获取输入文本。

hello world

其次,将字符串转换为三进制(以3为底)。使用此键:

a = 000
b = 001
c = 002
d = 010
e = 011
f = 012
g = 020

...

w = 211
x = 212
y = 220
z = 221
[space] = 222

使用此键,hello world将变为021011102102112222211112122102010,如下所示。

 h   e   l   l   o       w   o   r   l   d
021 011 102 102 112 222 211 112 122 102 010

第三,将第一个数字移到末尾。

021011102102112222211112122102010
becomes
210111021021122222111121221020100

第四,使用相同的键将数字转换回字符串。

210 111 021 021 122 222 111 121 221 020 100
 v   n   h   h   r       n   q   z   g   j

最后,返回加密的文本。

vnhhr nqzgj

以下是一些示例文本及其输出:

the turtle ==> dvo fh ego

python ==> uudwqn

code golf ==> hpjoytqgp

因为这是代码高尔夫,所以以字节为单位的最短条目将获胜。如果某些字符不是小写字母或空格,则允许错误。这是我的第一个挑战,因此任何建议都将大有帮助。

祝好运!

排行榜:

var QUESTION_ID=54643;function answersUrl(e){return"http://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),e.has_more?getAnswers():process()}})}function shouldHaveHeading(e){var a=!1,r=e.body_markdown.split("\n");try{a|=/^#/.test(e.body_markdown),a|=["-","="].indexOf(r[1][0])>-1,a&=LANGUAGE_REG.test(e.body_markdown)}catch(n){}return a}function shouldHaveScore(e){var a=!1;try{a|=SIZE_REG.test(e.body_markdown.split("\n")[0])}catch(r){}return a}function getAuthorName(e){return e.owner.display_name}function process(){answers=answers.filter(shouldHaveScore).filter(shouldHaveHeading),answers.sort(function(e,a){var r=+(e.body_markdown.split("\n")[0].match(SIZE_REG)||[1/0])[0],n=+(a.body_markdown.split("\n")[0].match(SIZE_REG)||[1/0])[0];return r-n});var e={},a=1,r=null,n=1;answers.forEach(function(s){var t=s.body_markdown.split("\n")[0],o=jQuery("#answer-template").html(),l=(t.match(NUMBER_REG)[0],(t.match(SIZE_REG)||[0])[0]),c=t.match(LANGUAGE_REG)[1],i=getAuthorName(s);l!=r&&(n=a),r=l,++a,o=o.replace("{{PLACE}}",n+".").replace("{{NAME}}",i).replace("{{LANGUAGE}}",c).replace("{{SIZE}}",l).replace("{{LINK}}",s.share_link),o=jQuery(o),jQuery("#answers").append(o),e[c]=e[c]||{lang:c,user:i,size:l,link:s.share_link}});var s=[];for(var t in e)e.hasOwnProperty(t)&&s.push(e[t]);s.sort(function(e,a){return e.lang>a.lang?1:e.lang<a.lang?-1:0});for(var o=0;o<s.length;++o){var l=jQuery("#language-template").html(),t=s[o];l=l.replace("{{LANGUAGE}}",t.lang).replace("{{NAME}}",t.user).replace("{{SIZE}}",t.size).replace("{{LINK}}",t.link),l=jQuery(l),jQuery("#languages").append(l)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",answers=[],page=1;getAnswers();var SIZE_REG=/\d+(?=[^\d&]*(?:&lt;(?:s&gt;[^&]*&lt;\/s&gt;|[^&]+&gt;)[^\d&]*)*$)/,NUMBER_REG=/\d+/,LANGUAGE_REG=/^#*\s*([^,]+)/;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"><div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table></div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table></div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody></table><table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody></table>


3
请注意,从技术上讲,这是混淆,不是加密。这里没有加密密钥。
John Dvorak

@JanDvorak“密码”会起作用吗?
乌龟

为了以@JanDvorak的评论为基础,我将其描述为“编码”,这是一种以不同格式表示数据的标准方法(例如,您可以使用十六进制编码或base64编码表示位字符串)。
a药

1
@JanDvorak同意-我更可能将ROT13称为“混淆”而不是“编码”(即使它同时满足这两个定义)。可能最准确的标题是“ ...混淆文字”
apsillers

2
@TheTurtle的想法是uint64使用的递增幂将字符打包成一个大整数()27。移位一位数字就等于将该大整数乘以3,并且在另一端引入第一个数字将只是一个加法。但是有一些复杂性,例如丢弃最后一个“进位”(也许通过mod操作),而我却无法用很少的字节来工作
Luis Mendo

Answers:


16

Pyth,23 22字节

sXc.<sXz=+GdJ^UK3K1KJG

在线尝试:常规输入 / 测试套件

感谢@isaacg提供了一个字节。

说明:

sXc.<sXz=+GdJ^UK3K1KJG
        =+Gd             append a space the G (preinitialized with the alphabet)
               K3        assign 3 to K
            J^UK K       assign all 3-digit ternary numbers 
                         [[0,0,0], [0,0,1],...,[2,2,2]] to J
      Xz  G J            translate input from G to J
     s                   sum (join all ternary numbers to one big list)
   .<             1      rotate by 1
  c                K     split into lists of size 3
 X                  JG   translate from J to G
s                        join chars to string and print

1
我们有相同的想法。我写了CJam的Pyth端口,然后向下滚动并看到了您的答案:/
Andrea Biondo

1
你可以做一个增量赋值保存字节G,而不是使用N,如=+Gd
isaacg 2015年

@isaacg谢谢。
雅库布

14

Pyth,26个字节

J+Gds@LJiR3c.<s.DR9xLJz1 2

在Pyth编译器/执行器中在线尝试:demo | 测试用例

理念

假设所有输入字符都已映射到步骤2指定的整数。

对于每个3位数的三进制数,我们有xyz 3 = 9x + 3y + z,因此除以9的模除得到商x和余数3y + z

如果输入为abc 3 def 3 ghi 3,则对每个模块应用模除得到a,3b + c,d,3e + f,g,3h + i

将列表从上方一个单位向左旋转后,我们可以将整数分为几对。这产生了列表(3b + c,d),(3e + f,g),(3h + i,a)

现在,如果将(3y + z,w)从基数3转换为整数,我们将获得3(3y + z)+ w =​​ 9y + 3z + w =​​ zyw 3

因此,将基数转换应用到对列表中可以得到bcd 3 efg 3 hia 3,这正是将连接的三进制数向左旋转一个单位的结果。

剩下要做的就是将结果整数映射回字符。

J+Gd                        Concatenate "a...z" (G) with " " (d) and save in J.
                    L z     For each character in the input(z):
                   x J        Compute its index in J.
                 R          For each index I:
               .D 9           Compute (I / 9, I % 9).
              s             Concatenate the resulting pairs.
            .<         1    Rotate the resulting list one unit to the left.
           c             2  Split it back into pairs.
         R                  For each pair:
        i 3                   Perform conversion from base 3 to integer.
      L                     For each resulting integer:
     @ J                      Select the element of J at that index.
    s                       Concatenate the resulting characters.

是的,几个小时后我就被CJam和Pyth打败了。:/
kirbyfan64sos

哇!您能写出它如何工作的解释吗?我很好奇。:)
乌龟

@TheTurtle我已经编辑了答案。
丹尼斯

10

python 2,96

s=input()
r=y=''
for c in s+s[0]:x=(ord(c)-97)%91;r+=y and chr((y%9*3+x/9-26)%91+32);y=x
print r

将字符转换为as c的值,其模数仅影响空格以将其转换为26。反向转换为to ,其中模数仅影响使其变为空格。xx=(ord(c)-97)%91ichr((i-26)%91+32)i=26

我们遍历字符,注意当前值x和上一个值y。我们使用的最后两个三进制数字(y作为y%9)和的第一个三进制数字(x作为)x/9。串联的值为y%9*3+x/9。可能有一些将这种算法与97空间平移和固定相结合的优化。

我们进行循环,然后返回到字符串的最后一个字符。我们还执行一个准备循环以写入先前的值y,在y尚未初始化时抑制第一个循环的字符。


8

CJam,39个 29字节

关于这一点,最酷的是它甚至不使用基本转换。

q'{,97>S+:XZZm*:Yere_(+3/YXer

在线尝试

我只是意识到我的想法与Jakube的Pyth答案完全相同。实际上,在看到他的帖子之前,我实际上将此CJam代码移植到了Pyth,最后以25个字节结尾。考虑到这是我第一次参加Pyth高尔夫,我想还算不错。

说明

                              e# Z = 3
q                             e# Push input string
 '{,                          e# Push ['\0' ... 'z']
    97>                       e# Keep ['a' ... 'z']
       S+                     e# Append space
         :X                   e# Assign "a...z " to X
           ZZm*               e# Push 3rd cartesian power of [0 1 2]
                              e# i.e. all 3-digit permutations of 0, 1, 2
                              e# (in lexicographical order)
               :Y             e# Assign those permutations to Y
                 er           e# Translate input from X to Y
                   e_         e# Flatten resulting 2D array
                     (+       e# Rotate first element to the end
                       3/     e# Split back into 3-digit elements
                         YXer e# Translate from Y to X

7

CJam,30 29 27字节

q'{,97>S+:Af#9fmd(+2/3fbAf=

CJam解释器中在线尝试。

方法与我的其他答案相同,这是此代码与Pyth的移植。

怎么运行的

q                           e# Read from STDIN.
 '{,                        e# Push ['\0' ... 'z'].
    97>                     e# Remove the first 97 elements (['\0' - '`']).
       S+:A                 e# Append a space and save in A.
           f#               e# Find the index of each input character in A.
             9fmd           e# Apply modular division by 9 to each index.
                 (+         e# Shift out the first quotient and append it.
                   2/       e# Split into pairs.
                     3fb    e# Convert each pair from base 3 to integer.
                        Af= e# Select the corresponding elements from A.


6

Javascript(ES6),175个字节

一线!

“过度使用可变v奖励,有人吗?”

更新:现在使用名为的变量v,这很让人困惑!

感谢@vihan保存6个字节!

感谢@Neil节省了27个字节!!

v=>(([...v].map(v=>(v<"V"?53:v.charCodeAt()-70).toString(3).slice(1)).join``)+v[0]).slice(1).match(/..?.?/g).map(v=>(v=String.fromCharCode(parseInt(v,3)+97))>"z"?" ":v).join``

定义一个匿名函数。要使用v=该功能,请在代码之前添加以为该函数起一个名称,然后像这样调用它alert(v("hello world"))


您可以使用.slice(-3)保存6个字节,此时您可以使用"00"+v保存另一个字节。(您可以使用模板进行连接,但是长度是相同的。)
Neil

实际上,在将值转换为基数3之前,您可以在值上加上27以节省一大堆字节,因为这样可以保证有足够的位数。.map(v=>(v<"V"?26:v.charCodeAt()-97).toString(3)).map(v=>("000"+v).slice(v.length))然后成为.map(v=>(v<"V"?53:v.charCodeAt()-70).toString(3).slice(1))
尼尔

@Neil哇,这真的缩短了代码!通过删除唯一的中间变量,它也使它成为真正的“单线”。谢谢!
jrich

5

朱莉娅149个 137字节

我的第一个高尔夫!

s->(j=join;b=j([base(3,i==' '?26:i-'a',3)for i=s]);r=b[2:end]*b[1:1];j([i==26?" ":i+'a'for i=[parseint(r[i:i+2],3)for i=1:3:length(r)]]))

(部分)取消高尔夫:

f = s -> (
    # join the ternary represenations:
    b = join([base(3, i == ' ' ? 26 : i - 'a',3) for i = s]);
    # rotate:
    r = b[2:end] * b[1:1];
    # calculate the new numbers:
    n = [parseint(r[i:i+2],3) for i = 1:3:length(r)];
    # convert back to characters:
    join([i == 26 ? " " : 'a' + i for i = n])
)
assert(f("hello world") == "vnhhr nqzgj")
assert(f("the turtle")  == "dvo fh ego")
assert(f("python")      == "uudwqn")
assert(f("code golf")   == "hpjoytqgp")

您可以使用=而不是infor循环,也可以b[1]代替使用b[1:1]。您也不需要在封闭括号和之间留一个空格for
Alex A.

@AlexA。为欢呼=,但b[1]返回一个字符,该字符不能用附加到字符串中*
kevinsa5

哦,对了,忘记了。
Alex A.

@AlexA。该for技巧是极好的。您也可以在引号后直接使用它。我没有意识到解析器是如此灵活。
kevinsa5 2015年

它也可以直接跟随数字文字end
Alex A.

4

使用Javascript(ES6),178172,170

p=>{p=p.replace(' ','{');c="";l=p.length;for(i=0;i<l;){c+=String.fromCharCode(((p.charCodeAt(i)-97)%9)*3+(((p.charCodeAt((++i)%l)-97)/9)|0)+97)}return c.replace('{',' ')}

用按位或替换Math.floor。创建了一个匿名函数。如果我没有正确理解,这应该可以解决我的烦恼(感谢Dennis!),并使我再减少2个字节。


3

朱莉娅169个 166字节

s->(J=join;t=J(circshift(split(J([lpad(i<'a'?"222":base(3,int(i)-97),3,0)for i=s]),""),-1));J([c[j:j+2]=="222"?' ':char(parseint(c[j:j+2],3)+97)for j=1:3:length(t)]))

取消+说明:

function f(s::String)
    # Convert the input into a string in base 3, with space mapping to 222
    b = join([lpad(i < 'a' ? "222" : base(3, int(i) - 97), 3, 0) for i = s])

    # Split that into a vector of single digits and shift once
    p = circshift(split(b, ""), -1)

    # Join the shifted array back into a string
    t = join(p)

    # Convert groups of 3 back into characters
    c = [t[j:j+2] == "222" ? ' ' : char(parseint(t[j:j+2], 3) + 97) for j = 1:3:length(t)]

    # Return the joined string
    join(c)
end

3

Haskell,160字节

a!k|Just v<-lookup k a=v
x=['a'..'z']++" "
y="012";z=mapM id[y,y,y]
m(a:u:r:i:s)=[u,r,i]:m(a:s)
m[e,a,t]=[[a,t,e]]
main=interact$map(zip z x!).m.(>>=(zip x z!))

gh,这感觉太冗长了,但是至少我...以某种方式击败了Python。还有露比


3

使用Javascript(ES6),141 124 120个字节

信不信由你.... :-)

(t,i=0,c=w=>(t.charCodeAt(w)-123)%91+26)=>String.fromCharCode(...[...t].map(k=>(c(i)%9*3+c(++i%t.length)/9+65|0)%91+32))

与我的其他答案一样,这是一个匿名函数,需要先将其分配给变量,然后才能使用它。在这里尝试:

我以为我也许可以通过使用其他技术来减少以前的回答几个字节,所以我从类似Tekgno的技术开始,然后从那里打了个头。我在函数的参数部分初始化了一些变量,然后再次将所有内容填充到.map函数中。然后我意识到String.fromCharCode外部会更有效率.map。毕竟是说,做,我已经剃掉了超过30个 45字节!

编辑1:.replace使用类似于xnor的Python解决方案的技术,通过消除s 节省了17个字节。

好吧,也许是时候应对另一个挑战了。


2

Python 2中,182个 180字节

由于替换成本很高,因此该解决方案并不理想。试图找出避免方法。

b=lambda k:k and b(k/3)*10+k%3
s=''.join('%03d'%b(ord(x)-6-91*(x>' '))for x in input())
print`[chr(int((s[1:]+s[0])[i:i+3],3)+97)for i in range(0,len(s),3)]`[2::5].replace('{',' ')

输入就像"hello world"


您需要为输入中所需的引号计算2个字节,对吗?
mbomb007

@ mbomb007这就是我以前的想法,但是很多人告诉我,我不需要考虑这一点。
卡德,2015年

2

Mathematica,162个字节

r=Append[#->IntegerDigits[LetterNumber@#-1,3]~PadLeft~3&/@Alphabet[]," "->{2,2,2}];StringJoin[Partition[RotateLeft[Characters@#/.r//Flatten,1],3]/.(#2->#1&@@@r)]&

(重新)使用a Rule将数字列表转换为字符并返回。


2

Javascript(ES6),179个字节

s=>[...s+s[0]].map(q=>`00${(q<'a'?26:q.charCodeAt(0)-97).toString(3)}`.slice(-3)).join``.slice(1,-2).match(/..?.?/g).map(q=>q>221?' ':String.fromCharCode(parseInt(q,3)+97)).join``

支持.match正则表达式的道具。


1

露比(177)

each_char方法至少需要Ruby 1.9

l=[*('a'..'z'),' '];n=(0..26).map{|m|m=m.to_s(3).rjust 3,'0'};s='';gets.chomp.each_char{|x|s+=n[l.index x]};puts("#{s[1..-1]}#{s[0]}".scan(/.../).map{|i|i=l[n.index i]}.join '')

1

Java,458 449字节

这让我有点难过,以确定我可以不使用Java 8流和关闭10个字节刮胡子map()方法。

这是高尔夫球版:

import org.apache.commons.lang.ArrayUtils;class A{public static void main(String[]a){int b=0;String[] c=new String[27];for(;b<27;++b)c[b]=String.format("%03d",Integer.valueOf(Integer.toString(b,3)));String d=a[0],e="abcdefghijklmnopqrstuvwxyz ",f="",g="";for(b=0;b<d.length();++b)f+=c[e.indexOf(d.substring(b,b+1))];f=f.substring(1)+f.charAt(0);for(b=0;b<f.length();b+=3)g+=e.charAt(ArrayUtils.indexOf(c,f.substring(b,b+3)));System.out.println(g);}}

这是打高尔夫球的版本。它旨在可读,但我不做任何保证。

import org.apache.commons.lang.ArrayUtils;
class A {
    public static void main(String[] a) {
        int b=0;
        String[] c = new String[27];
        for (; b < 27; ++b)
            c[b] = String.format("%03d", Integer.valueOf(Integer.toString(b, 3)));
        String
            d = a[0],
            e = "abcdefghijklmnopqrstuvwxyz ",
            f = "",
            g = "";
        for (b = 0; b < d.length(); ++b)
            f += c[e.indexOf(d.substring(b, b + 1))];
        f = f.substring(1) + f.charAt(0);
        for (b = 0; b < f.length(); b += 3)
            g += e.charAt(ArrayUtils.indexOf(c, f.substring(b, b + 3)));
        System.out.println(g);
    }
}

该程序将字符串转换为命令行参数。如果要在输入中保留空格,则必须用双引号将其引起来。

我想提供一个在命令行中使用它的示例,但是我无法使此代码在Eclipse之外运行。我从未从命令行^ _ ^学会使用Java。您可以轻松地在自己选择的IDE中运行此程序。


如果仅使用ArrayUtils一次,则在代码中使用完全限定名称比该import语句短。请参阅:codegolf.stackexchange.com/a/16100/10801(链接答案的下半部分)
masterX244

1

使用Javascript(ES6),181个 180字节

t=>((x=[...t].map(k=>`00${(k<'!'?26:k.charCodeAt(0)-97).toString(3)}`.slice(-3)).join``).slice(1)+x[0]).match(/.../g).map(j=>j>221?' ':String.fromCharCode(parseInt(j,3)+97)).join``

这是一个匿名函数,因此在使用前需要给它命名。(例如encrypt=t=>...)在这里尝试:

我开始使用多个变量和for循环代替.map。然后,我在不改变算法的情况下以各种可能的方式打高尔夫球,这使我大约占了217个字节。在查看了UndefinedFunction的答案后,我设法将其降至195,对Dendrobium的答案进行了一些检查,结果又打了14球。

据我所知,我再也做不了什么,否则我的结果将与Dendrobium的结果几乎完全相同(除了缩短一个字符!)。谁能找到我保存一个字符的地方?:-)

和往常一样,我们很欢迎提出建议!


感谢您的正则表达式提示!我不确定将for-of循环如何精确地应用到此单行函数中,但是无论如何它可能会节省一些空间。您可以根据需要发布您的版本。
ETHproductions'Aug

0

Matlab,113个字节

x=dec2base(strrep(input('','s'),' ','{')-97,3)';strrep(char(base2dec(reshape(x([2:end 1]),3,[])',3)+97)','{',' ')

输入是通过stdin。

例:

>> x=dec2base(strrep(input('','s'),' ','{')-97,3)';strrep(char(base2dec(reshape(x([2:end 1]),3,[])',3)+97)','{',' ')
hello world
ans =
vnhhr nqzgj

0

朱莉娅-92 87 61 54字节

s->join(32+(3(i=[s...]%91+579)%27+i[[2:end,1]]÷9)%91)

取消高尔夫:

function f(s)
  t=[s...];       # Convert the string into a char array
                      #
  i=t%91+579          # Mod 91 drops the alpha characters to sit just
                      # below space, then 579 is added as a trick,
                      # equivalent to subtracting 6 and adding 9*65
  v1=3i%27            # This shifts the bottom two ternary digits up
                      # and removes the first ternary digit
  v2=i[[2:end,19    # This shifts the first ternary digit down and
                      # removes the bottom two ternary digits. [2:end,1]
                      # rotates the array to put the first value at the end
  N=(v1+v2)%91+32     # this combines the ternary digits, then returns
                      # the values to the correct ASCII values
  j=join(N)           # join the char array back to a string
  return j
end

trick俩可能会使您感到困惑。减去6将mod后的“ a”向下移动到零。将9 * 65添加到v1 + v2等于添加65,这是将值恢复为其ascii值的过程的一部分。您可以替换i=t%91+579i=t%91-6,然后替换N=(v1+v2)%91+32N=(v1+v2+65)%91+32以获得相同的结果,但是它需要一个额外的字符。

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.