Обчисліть зворотний XOR


13

Дозвольте fбути функцією, яка відображає бітфілд ( {0 1}) розміру n+1на бітфілд розміру n, застосовуючи XORдо iго та 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вони не застосовуються рекурсивно / ітеративно, натомість вихідний рядок безпосередньо обчислюється

Тестовий сценарій:

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}? Також я не розумію визначення f, звідки iберуться? Який другий аргумент XOR? як ми 111звідти 0101?
mniip

Яке краще ім’я? я позначає індекс
nvidia

Просто "бітфілд" зробив би. Що таке / значення / i? "0 XOR 1" = 1 "1 XOR 0" = 1 "0 XOR 1" = 1нічого не пояснює: я знаю, як працює XOR, але що саме ми XORing і де ми зберігаємо результат?
понеділок

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.
Марін

Відповіді:


14

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

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

Запустити його за допомогою введення з типу stdin (онлайн-перекладач: https://pyth.herokuapp.com/ ):

111
3

і результат буде записаний у stdout.

Це прямий переклад:

Пітон 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 к ) рази.


Я думаю, що ми зазвичай називаємо цю операцію "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> log 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 символів прибутку: с


Оновлення 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

АПЛ 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

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

Якщо я скопіюю, ((0,≠\)⍣⎕)⎕я отримаю недійсний маркер. Tryapl не може обробити матеріали?
randomra

1
Хмммм ... ти маєш рацію, так само і зі мною відбувається. Я використовую Dyalog APL, а потім tryapl просто для публікації тут, тому я ніколи не помічав, вибачте з цього приводу.
Моріс Зукка

5

CJam, 25 - 25 = 0 байт

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

Це лише прямий порт CJam відповіді GolfScript нижче, оскільки, прочитавши відповідь Мартина Бюттнера , я зрозумів, що можу зберегти один байт завдяки обробці CJam цілих чисел та символів. (В основному, CJam не потрібно 1&використовувати для примусового використання символів ASCII в біти в коді GolfScript, але вимагає попередньо qпрочитати вхідні дані.) Я б зазвичай вважав такий тривіальний порт дешевим трюком, але досягнення нульового балу зроблено це IMO варто.

У будь-якому випадку ця програма працює точно так само, як оригінальна програма GolfScript, наведена нижче, тому зверніться до її опису та інструкцій із використання. Як завжди, ви можете протестувати версію CJam за допомогою цього інтерпретатора .


GolfScript, 26 - 25 = 1 байт

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

Це рішення повторюється через рядок введення лише один раз, тому я вважаю, що він може отримати бонус -25 байт. Він працює, підтримуючи внутрішньо масив k -елементів, який зберігає поточний біт кожної з k -ітерацій.

Введення слід вводити через stdin у форматі "1111111" 3, тобто у вигляді цитованого рядка 0та 1символів, а потім цифрою 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 i , j : = b i , ( j −1)b ( i −1), ( j −1) ,

де b 0, j - j -й вхідний біт (для j ≥ 1), b k , j - j -й вихідний біт, а b i , 0 = 0 за припущенням. Різниця полягає в тому, що, хоча ітеративні рішення фактично обчислюють повторення "рядок за рядком" (тобто спочатку b 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

Пітон 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'.


Пітон 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

Перл 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.