Вычислить обратное XOR


13

Позвольте fбыть функцией, которая отображает битовое поле ( {0 1}) размера n+1в битовое поле размера n, применяя XORк ith-му и 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_inverseприменяется kк входному битовому полю. (то есть f_inverse(f_inverse(f_inverse(input))))

Критерии победы: наименьшее количество персонажей

Бонус:

-25Символы, если f_inverseне применяется рекурсивно / итеративно, вместо этого выходная строка вычисляется напрямую

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
Можете ли вы дать несколько тестов для проверки.
Оптимизатор

3
Не могли бы вы перестать называть их {0-1}-Bitfields? Также я не понимаю определение f, откуда это iвзялось? Каков второй аргумент XOR? как мы получаем 111от 0101?
Мниип

Какое имя лучше? я обозначаю индекс
nvidia

Просто «битфилд» подойдет. Что такое / значение / из i? "0 XOR 1" = 1 "1 XOR 0" = 1 "0 XOR 1" = 1ничего не объясняет: я знаю, как работает XOR, но что именно мы делаем XOR и где мы храним результат?
Мниип

9
Я думаю , что он означает: f([a,b,c,d]) = [a^b, b^c, c^d]. И он хочет инверсию этой функции, то есть f'([x,y,z]) = [a,b,c,d]такие , что a^b=x, b^c=y, c^d=z.
Marinus

Ответы:


14

Pyth, 33 30 - 25 = 5 байт

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

Запустите его с помощью ввода из stdin like (онлайн-переводчик: 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), и результат будет записан на стандартный вывод.

Обратите внимание, что мы ожидаем, что 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 k 2 k ) = 0, что означает f 2 k (x) = x, а обратное тривиально является тождественной функцией!

Поэтому стратегия для нахождения ф (х) , не вызывая е -1 (х) на все это:

  1. Найдите K такой, что:

    • K ≥ k
    • K> log 2 x
    • К является степенью 2
  2. Экспресс f -k (x) = f -K + (Kk) (x) = f -K (f K-k (x)) = f K-k (x)

  3. Таким образом, результат fназывается Кк раз

  4. 25 символов прибыли: р


Обновление 1 : используется восьмеричное представление вместо двоичного, чтобы мы могли использовать %форматирование для экономии большого количества байтов.

Обновление 2 : использовать периодическую структуру f. Отказался от итеративной версии, поскольку неитеративная версия короче даже без бонуса -25 байт.

Обновление 3 : уменьшено на 3 байта от Pyth, спасибо isaacg!


Как описано в советах: codegolf.stackexchange.com/a/45280/20080 вы можете заменить цикл for и назначения на уменьшение, например, так:Jiz8K+lzQ%"%0*o",KuxG/G8rQ^2KJ
isaacg

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 ^ конечно, просто дает целое число.

Таким образом, типы летают повсюду, но , к счастью, когда у меня есть целое число , это либо 0или , 1и всякий раз , когда у меня есть характер , это либо '0и '1и результат всегда желательно один (в любом типе). Поскольку строки - это просто массивы символов, смешивание символов с числами не является проблемой. И в конце, когда все напечатано, символы не получают специальных разделителей, поэтому на вывод не влияет то, какой бит представлен как число или символ.


Ваше превосходное объяснение поведения символьно-числового типа в CJam позволило мне сбрить байт моего решения , достигнув 25 - 25 = 0 байт. Спасибо и +1!
Илмари Каронен

2
Такое поведение ужасно (+1).
ballesta25

8

J, 17 символов

Всегда используя 0 в качестве ведущей цифры.

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

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

Начиная с 128 1-го состояния верхнего ряда (слева) и случайного состояния (справа), показывая последние 128 цифр в течение первой 129 итерации.

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

участок участок


6

APL 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|+\ ?
рандома

⎕ - это входные данные, если вы используете то же выражение, которое я написал, программа должна запросить у вас нужные числа, сначала двоичный вектор, а затем второй раз для числа итераций. Я использовал a и b в ссылке на tryapl, поэтому она выполняется без каких-либо дополнительных вещей. Также спасибо за !! \ !!
Морис Зукка

Если я копирую, ((0,≠\)⍣⎕)⎕я получаю недействительный токен. Tryapl не может обрабатывать ввод?
рандома

1
Хмммм ... ты прав, со мной происходит то же самое. Я использую Dyalog APL, а затем пытаюсь написать здесь, так что я никогда не заметил, извините за это.
Морис Цукка

5

CJam, 25 - 25 = 0 байт

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

Это просто прямой порт CJam из ответа GolfScript ниже, поскольку, прочитав ответ Мартина Бюттнера , я понял, что могу сохранить один байт благодаря обработке CJam целочисленных и символьных типов. (По сути, CJam не нуждается в 1&использовании, чтобы принудительно вводить символы ASCII в биты в коде GolfScript, но требует предварительно добавленногоq для чтения ввода.) Обычно я считаю такой тривиальный порт дешевым трюком, но достижение нулевого результата сделало ИМО стоит.

В любом случае, эта программа работает точно так же, как оригинальная программа GolfScript ниже, поэтому, пожалуйста, обратитесь к ее описанию и инструкциям по использованию. Как обычно, вы можете протестировать версию CJam с помощью этого онлайн-переводчика .


GolfScript, 26 - 25 = 1 байт

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

Это решение перебирает входную строку только один раз, поэтому я считаю, что оно соответствует бонусу в 25 байт. Он работает путем внутреннего поддержания массива k- элементов, в котором хранится текущий бит каждого из k предварительных итераций.

Ввод должен быть "1111111" 3сделан через stdin, в формате , то есть в виде строки 0и 1символов в кавычках , за которыми следует число k . Вывод будет в стандартный вывод, как цепочка бит без кавычек.

Протестируйте этот код онлайн. (Если время ожидания программы истекло, попробуйте перезапустить ее; сервер 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

В основном, как и большинство итерационных решений, этот код можно понимать как применение повторения

        б я , J : = Ь I , ( J - 1)б ( я -1), ( J - 1) ,

где b 0, j - j-й входной бит (для j ≥ 1), b k , j - j-й выходной бит и b i , 0 = 0 по предположению. Разница заключается в том, что, в то время как итерационных решениях, в сущности, вычислить «строку за строкой» рекуррентной (т.е. первого б 1, j для всех j , затем b 2, j и т. Д.), Это решение вместо этого вычисляет его «столбец путем столбец "(или, точнее," диагональ по диагонали "), сначала вычисляя b i , i для 1 ≤ ik , затем b i , i +1 , затем b i , i +2 и т. Д.

Одно (теоретическое) преимущество этого подхода состоит в том, что в принципе этот метод может обрабатывать произвольно длинную входную строку, используя только O ( k ) память. Конечно, интерпретатор GolfScript автоматически считывает все вводимые данные в память перед тем, как запустить программу, в основном сводя на нет это преимущество.


2

Питон, 94 78

Будет выполнен по крайней мере один раз и, следовательно, даст тот же результат для n=0иn=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

Python 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вычисляет последовательные различия и gсоставляет fс собой n раз.

Функция 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

Я должен был внимательно прочитать спецификацию (facepalm)
Qwertiy

1

C # - 178 161 115 символов

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.