计算逆XOR


13

f是位域(映射函数{0 1}的大小)n+1大小的位域n应用XORi日和i+1次位并将结果写入新位域。

例: f("0101") = "111"

非正式计算:

0 XOR 1 = 1

1 XOR 0 = 1

0 XOR 1 = 1

f_inverse是的反函数f。由于逆不是唯一的,因此f_inverse返回一个有效的解决方案。

输入:位字段为字符串(即"0101111101011")和给定的自然数k

输出:位字段作为字符串,因此如果f_inversek时间应用于输入位字段,则字符串包含结果。(即f_inverse(f_inverse(f_inverse(input)))

获奖标准:人物最少

奖金:

-25如果f_inverse不递归/迭代地应用字符if ,则直接计算输出字符串

Testscript:

a = "011001"
k = 3

def f(a):
    k = len(a)
    r = ""
    for i in xrange(k-1):
        r += str(int(a[i]) ^ int(a[i+1]))
    return r

def iterate_f(a, k):
    print "Input ", a
    for i in xrange(k):
        a = f(a)
        print "Step " + str(i+1), a

iterate_f(a, k)

例如,您可以在此处粘贴它,然后尝试。


3
您能否给出一些测试用例进行验证。
Optimizer

3
您能不能再叫它们{0-1}-Bitfields?我也不明白的定义f,它i来自哪里?XOR的第二个论点是什么?我们怎样才能1110101
mniip 2015年

什么叫更好的名字?我表示索引
nvidia

只需“位域”即可。什么是/ value / i"0 XOR 1" = 1 "1 XOR 0" = 1 "0 XOR 1" = 1什么也没解释:我知道XOR的工作原理,但是我们究竟对XOR进行什么运算,并将结果存储在哪里?
mniip'2

9
我认为他的意思是:f([a,b,c,d]) = [a^b, b^c, c^d]。他希望该函数的反函数,即f'([x,y,z]) = [a,b,c,d]这样a^b=xb^c=yc^d=z
marinus'2

Answers:


14

Pyth, 33 30-25 = 5个字节

Jiz8K+lzQ%"%0*o",KuxG/G8rQ^2KJ

通过来自stdin的输入(例如,在线解释器:https : //pyth.herokuapp.com/)运行它:

111
3

并将结果写入标准输出。

这是以下内容的直接翻译:

Python 2 127 118 79-25 = 54字节

def i(s,k):
 l=int(s,8);t=len(s)+k
 while k<1<<t:l^=l/8;k+=1
 print'%0*o'%(t,l)

像这样调用它i("111", 3),结果将被写入stdout。

请注意,我们期望k不会太大,因为出于代码搜寻的目的,内部循环将运行O(2 k)次。


我认为我们通常将此操作称为“ xorshift”之类的东西。如果我们将输入表示为大端整数,那么函数f就是:

  • f(x)= x⊕(x≫ 1)

如果我们两次应用f,我们将得到:

  • f 2(x)= x⊕(x≫ 2)

但是,应用3次将具有不同的模式:

  • f 3(x)= x⊕(x≫ 1)⊕(x≫ 2)⊕(x≫ 3)

应用4次回到基本形式:

  • f 4(x)= x⊕(x≫ 4)

等等:

  • f 2 k(x)= x⊕(x≫ 2 k

请注意,如果我们选择一个足够大的2 k,则(x≫ 2 k)= 0,意味着f 2 k(x)= x,而逆反而是恒等式!

因此找到f -k(x)而不调用f -1(x)的策略是:

  1. 找到K使得:

    • K≥k
    • K>对数2 x
    • K是2的幂
  2. 表示f -k(x)= f -K +(Kk)(x)= f -K(f K-k(x))= f K-k(x)

  3. 因此,结果f称为Kk倍

  4. 25个字符的利润:p


更新1:使用八进制表示形式而不是二进制形式,因此我们可以使用%格式设置来节省大量字节。

更新2:利用的周期性结构f。淘汰了迭代版本,因为即使没有-25字节的奖励,非迭代版本也会更短。

更新3:感谢isaacg,从Pyth减少了3个字节!


如提示所述:codegolf.stackexchange.com/a/45280/20080,您可以用reduce代替for循环和赋值,如下所示:Jiz8K+lzQ%"%0*o",KuxG/G8rQ^2KJ
isaacg 2015年

11

CJam,15个 14字节

l~{0\{1$^}/]}*

像输入

"111" 3

在这里测试。

说明

l~{0\{1$^}/]}*
l~             "Read and evaluate input.";
  {         }* "Repeat k times.";
   0\          "Push a 0 and swap it with the string/array.";
     {   }/    "For each element in the string/array.";
      1$       "Copy the previous element.";
        ^      "XOR.";
           ]   "Wrap everything in a string/array again.";

结果将自动打印在程序末尾。

我之所以说“字符串/数组”,是因为我从一个字符串(只是一个字符数组)开始,但是我一直在它们之间以及数字之间进行XOR。Character Character ^给出一个整数(基于代码点的XOR),Character Integer ^Integer Character ^给出一个字符(基于数字与代码点的XOR-解释为代码点)。而Integer Integer ^当然只是给出了一个整数。

所以类型随处可见,但是幸运的是,每当我有一个整数时,要么是要么01而每当我有一个字符时,要么都是'0'1而且结果始终是所需的(无论哪种类型)。由于字符串只是字符数组,所以将字符与数字混合根本不是问题。最后,在打印完所有内容后,字符没有特殊的定界符,因此输出不受位表示为数字或字符的影响。


您对CJam中的字符/数字类型行为的出色解释使我从解决方案中减少了一个字节,达到25 − 25 = 0字节。谢谢,+ 1!
Ilmari Karonen

2
这种类型的行为令人恐惧(+1)。
ballesta25'2

8

J,17个字符

始终使用0作为前导数字。

   (~:/\@]^:[,~[$0:)

   3 (~:/\@]^:[,~[$0:) 1 1 1 
0 0 0 1 0 0

从第一行的128 1的状态(左)和随机状态(右)开始,显示前129次迭代的最后128位。

   viewmat (~:/\)^:(<129) 128$1               viewmat (~:/\)^:(<129) ?128$2

情节 情节


6

杀伤人员地雷11

((0,≠\)⍣⎕)⎕

说明:

≠\  compare increasing number of elements (1 1 1 ->1 0 1)
0,    add a starting zero
()⍣⎕  repeat the function in parenthesis ⎕ times, ⎕ is the second argument
()⎕   apply all to ⎕, that is first argument

尝试tryapl.org


无法在tryapl上运行它(如何提供输入?),而≠\ 不是不能运行2|+\
randomra 2015年

are是输入,如果您使用与我编写的相同的表达式,则程序应要求您提供所需的数字,首先是二进制矢量,然后是第二次要求迭代次数。我在tryapl的链接中使用了a和b,因此它执行时没有askin的东西。也感谢≠\ !!
莫里斯·祖卡

如果我复制,((0,≠\)⍣⎕)⎕则会得到无效的令牌。Tryapl无法处理输入?
randomra 2015年

1
嗯...你是对的,对我来说也是一样。我正在使用Dyalog APL,然后尝试将tryapl张贴在这里,所以我从没注意到,对此感到抱歉。
莫里斯·祖卡

5

CJam,25 − 25 = 0字节

q~1,*_@{[\{1$^}/_](;)\}/;

这是仅低于GolfScript答案的直CJam端口,因为看完之后马丁布特内尔的答案,我意识到,我可以一个字节保存由于CJam的处理整数和字符类型。(从根本上讲,CJam不需要1&用来将ASCII字符强制转换为GolfScript代码中的位,但确实需要一个前缀q来读取输入。)我通常认为这种琐碎的端口是一个便宜的把戏,但取得零分这对海事组织来说是值得的。

无论如何,该程序的工作方式与下面的原始GolfScript程序完全相同,因此请参考其说明和使用说明。像往常一样,您可以使用此在线解释器测试CJam版本。


GolfScript,26 − 25 = 1字节

~1,*.@{[1&\{1$^}/.](;)\}/;

该解决方案仅对输入字符串进行一次迭代,因此我相信它有资格获得−25字节的奖励。它通过内部维护一个k元素数组来工作,该数组存储k个预迭代中的每一个的当前位。

输入应通过stdin进行,格式为"1111111" 3,例如,带引号的字符串01字符,后跟数字k。输出将以不带引号的位串的形式输出到stdout。

在线测试此代码。(如果程序超时,请尝试重新运行它; Web GolfScript服务器因随机超时而臭名昭著。)


这是该程序的扩展版本,带有注释:

~             # eval the input, leaving a string and the number k on the stack

1,*           # turn the number k into an array of k zeros ("the state array")
.             # make a copy of the array; it will be left on the stack, making up the
              # first k bits of the output (which are always zeros)

@             # move the input string to the top of the stack, to be iterated over
{
  [           # place a start-of-array marker on the stack, for later use
  1&          # zero out all but the lowest bit of this input byte
  \           # move the state array to the top of the stack, to be iterated over

  { 1$^ } /   # iterate over each element of the state array, XORing each
              # element with the previous value on the stack, and leave
              # the results on the stack

  .           # duplicate the last value on the stack (which is the output bit we want)
  ]           # collect all values put on the stack since the last [ into an array
  (;          # remove the first element of the array (the input bit)
  )           # pop the last element (the duplicated output bit) off the array
  \           # move the popped bit below the new state array on the stack
}
/             # iterate the preceding code block over the bytes in the input string

;             # discard the state array, leaving just the output bits on the stack

基本上,像大多数迭代解决方案一样,此代码可以理解为应用递归

        b Ĵ:= b ,(Ĵ -1)b -1),(Ĵ -1)

其中b 0,ĴĴ个输入比特(对Ĵ ≥1),b ķĴĴ个输出比特,和b ,0 = 0通过假设。所不同的是,而迭代解决方案,实际上,“逐行”计算复发(即,第一b 1,Ĵ所有Ĵ,然后b 2,Ĵ等),该解决方案,而不是计算其“列由列”(或更准确地说,是“对角线对角线”),首先计算b ii等于1≤iķ,然后b 1,然后b 2

这种方法的一个(理论上的)优点是,原则上,此方法可以仅使用O(k)存储来处理任意长的输入字符串。当然,无论如何运行程序之前,GolfScript解释器都会自动将所有输入读入内存,这在很大程度上抵消了这一优势。


2

蟒蛇,94 78

将至少一次被执行,从而给出了相同的结果n=0n=1

def f(x,n):
 c='0'
 for i in x:c+='10'[i==c[-1]]
 return f(c,n-1)if n>1 else c

旧版本将字符串转换为数字数组并以模2形式“积分”

from numpy import*
g=lambda x,n:g(''.join(map(str,cumsum(map(int,'0'+x))%2)),n-1)if n>0 else x

2

蟒蛇2,68

g=lambda l,n,s=0:n and g(`s`+(l and g(l[1:],1,s^(l>='1'))),n-1)or l

彻底的解决方案。分为两个功能更容易理解

f=lambda l,s=0:`s`+(l and f(l[1:],s^(l>='1')))
g=lambda l,n:n and g(f(l),n-1)or l

其中f计算连续的差异并与自身进行n次g合成f

该函数f计算的累加XOR和l,这是对连续XOR差的逆运算。由于输入是以字符串形式给出的,因此我们需要提取字符串,int(l[0])但要比字符串比较短l>='1'


Python 2、69

使用exec循环的迭代解决方案要长1个字符。

l,n=input()
exec"r=l;l='0'\nfor x in r:l+='10'[l[-1]==x]\n"*n
print l

也许有一种处理字符串的较短方法。如果我们可以让输入/输出是数字列表,则可以节省5个字符

l,n=input()
exec"r=l;l=[0]\nfor x in r:l+=[l[-1]^x]\n"*n
print l

1

Perl 5,34

#!perl -p
s/ .*//;eval's/^|./$%^=$&/eg;'x$&

在标准输入上给定的参数,以空格分隔。

$ perl a.pl  <<<"1101 20"
101111011011011011010110

1

Javascript ES6,47个字符

f=(s,k)=>k?f(0+s.replace(s=/./g,x=>s^=x),--k):s

顺便说一句,没有副作用:)


您需要接受ak参数作为迭代次数。(-25奖金用于计算迭代结果而无需实际执行迭代。)
Brilliand 2015年

我应该仔细阅读规格(facepalm)
Qwertiy

1

C#-178161115 字符

static string I(string a, int k){var s = "0";foreach(var c in a)s+=c==s[s.Length-1]?'0':'1';return k<2?s:I(s,--k);}

脱开背带

using System;
using System.Text;

namespace InverseXOR
{
    class Program
    {
        static string I(string a, int k)
        {
            var s = "0";
            foreach (var c in a)
                s += c == s[s.Length - 1] ? '0' : '1';
            return k < 2 ? s : I(s, --k);
        }

        static void Main(string[] args)
        {
            Console.WriteLine(I(args[0], Convert.ToInt32(args[1])));
        }
    }
}

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.