Фізика бітів


21

Фон

Так, фізика гризків - це реальна річ . Ідея полягає в тому, щоб побудувати нову теорію фізики, використовуючи лише рядки бітів, які розвиваються за імовірнісним правилом ... чи щось. Незважаючи на те, що прочитав про це пару паперів, я все ще досить розгублений. Тим не менше, всесвітній бітстринг створює хороший гольф з невеликим кодом.

Програма Всесвіту

Фізика бітстрингу відбувається в так званій програмній всесвіті . На кожному кроці еволюції Всесвіту є кінцевий список Lбіткових рядків деякої довжини k, починаючи з двоелементного списку, [10,11]де k = 2. Один часовий крок обробляється наступним чином (у псевдокоді, подібному до Python).

A := random element of L
B := random element of L
if A == B:
    for each C in L:
        append a random bit to C
else:
    append the bitwise XOR of A and B to L

Всі випадкові вибори рівномірно випадкові та незалежні один від одного.

Приклад

Приклад еволюції 4 кроків може виглядати наступним чином. Почніть з початкового списку L:

10
11

Ми вибираємо випадковим чином, A := 10і B := 10це той самий рядок, а це означає, що нам потрібно розширити кожну рядок Lвипадковим бітом:

101
110

Далі ми вибираємо A := 101і B := 110, оскільки вони не рівні, додаємо їх XOR до L:

101
110
011

Потім ми вибираємо A := 011і B := 110, і знову додаємо їх XOR:

101
110
011
101

Нарешті, ми вибираємо A := 101(останній рядок) і B := 101(перший рядок), які рівні, тому розширюємо випадковими бітами:

1010
1100
0111
1010

Завдання

Ваше завдання - взяти tяк вхідне невід’ємне ціле число , імітувати всесвіт програми на tетапі часу, а також повернути або роздрукувати отриманий список L. Зауважте, що t = 0результати виходять з початкового списку [10,11]. Ви можете виводити Lу вигляді списку цілих чисел, списків булевих значень або списку рядків; якщо висновок переходить до STDOUT, ви також можете надрукувати біт-рядки по одному в рядку у певному розумному форматі. Порядок бітстрингу є значним; зокрема, початковий список не може бути [11,10], [01,11]або що - небудь подібне. І функції, і повні програми прийнятні, стандартні лазівки заборонені, а найнижчий байт виграє.


Чи можемо ми обмежити довжину бітових рядків (тобто: чи можу я використовувати 32 бітові числа та бітові операції)?
edc65

1
@ edc65 Ні, довжина рядків може бути довільно високою.
Згарб

3
@ edc65 Очікувані вимоги до часу та пам'яті для отримання понад 32 біт є астрономічними, але це просто підходить, оскільки ми моделюємо Всесвіт. ;)
Згарб

5
Чи є ця фізика бітових струн крак-потом? Я не прочитав увесь документ, але фразу Ми використовували фізику бітових струн, щоб дати теорію, в якій наближення hbar c / e2 = 22 - 1 + 23 - 1 + 27 - 1 = 137 має сенс з точки зору комп’ютерний алгоритм та теорія інформації вражають мене трохи ... нумерологічним.
xebtl

1
@xebtl Мені це теж здається божевільним. Я пам'ятаю, як десь читав виправдання алгоритму, і це звучало скоріше як погана псевдофілософія, ніж фізика. Крім того, ваш опис алгоритму, схоже, відповідає моїй версії, можливо, я якимось чином не розумію вас.
Згарб

Відповіді:


7

Pyth, 27 26 байт

u?+RO2GqFKmOG2aGxVFKQ*]1U2

Спробуйте в Інтернеті: Демонстрація

Пояснення:

                              implicit: Q = input number
                     *]1U2    the initial list [[1,0], [1,1]]
u                   Q         reduce, apply the following expression Q times to G = ^
          mOG2                  take two random elements of G
         K                      store in K
       qF                       check if they are equal
 ?                              if they are equal:
  +RO2G                           append randomly a 0 or 1 to each element of G
                                else:
              aG                  append to G
                xVFK              the xor of the elements in K

xVFKеквівалентно xMK.
isaacg

@isaacg Ні, xVFKеквівалентно xMCKтакому ж кількості байтів.
Якубе

11

CJam, 42 40 38 37 байт

1 байт, збережений Sp3000.

B2b2/q~{:L_]:mR_~#L@~.^a+L{2mr+}%?}*p

Пояснення

Створіть початковий стан у вигляді базового числа 2:

B2b e# Push the the binary representation of 11: [1 0 1 1]
2/  e# Split into chunks of 2 to get [[1 0] [1 1]]

А потім виконайте основний цикл і досить роздрукуйте результат наприкінці:

q~       e# Read and eval input t.
{        e# Run this block t times.
  :L     e#   Store the current universe in L.
  _]     e#   Copy it and wrap both copies in an array.
  :mR    e#   Pick a random element from each copy.
  _~     e#   Duplicate those two elements, and unwrap them.
  #      e#   Find the second element in the first. If they are equal, it will be found at
         e#   index 0, being falsy. If they are unequal, it will not be found, giving
         e#   -1, which is truthy.

         e#   We'll now compute both possible universes for the next step and then select
         e#   the right one based on this index. First, we'll build the one where they were
         e#   not equal.

  L@~    e#   Push L, pull up the other copy of the selected elements and unwrap it.
  .^     e#   Take the bitwise XOR.
  a+     e#   Append this element to L.

  L      e#   Push L again.
  {      e#   Map this block onto the elements in L.
    2mr+ e#     Append 0 or 1 at random. 
  }%     
  ?      e#   Select the correct follow-up universe.
}*
p        e# Pretty-print the final universe.

Перевірте це тут.


6

Джулія, 141 129 байт

t->(L=Any[[1,0],[1,1]];for i=1:t r=1:length(L);A=L[rand(r)];B=L[rand(r)];A==B?for j=r L[j]=[L[j],rand(0:1)]end:push!(L,A$B)end;L)

Нічого розумного. Створює неназвану функцію, яка приймає ціле число як вхідне і повертає масив масивів. Щоб зателефонувати, дайте ім’я, наприклад f=t->....

Недоліки + пояснення:

function f(t)
    # Start with L0
    L = Any[[1,0], [1,1]]

    # Repeat for t steps
    for i = 1:t
        # Store the range of the indices of L
        r = 1:length(L)

        # Select 2 random elements
        A = L[rand(r)]
        B = L[rand(r)]

        if A == B
            # Append a random bit to each element of L
            for j = r
                L[j] = [L[j], rand(0:1)]
            end
        else
            # Append the XOR of A and B to L
            push!(L, A $ B)
        end
    end

    # Return the updated list
    L
end

Приклади:

julia> f(4)
4-element Array{Any,1}:
 [1,0,1,0]
 [1,1,1,1]
 [0,1,1,0]
 [0,1,0,0]

julia> f(3)
3-element Array{Any,1}:
 [1,0,1,1]
 [1,1,1,0]
 [0,1,0,1]

Збережено 12 байт завдяки ML!


Ви можете поголити його до 133 символів, якщо ви використовуєте оператор ternay замість if / else і якщо ви змінили A=something;B=something else to A,B=something,something else:t->(L=Any[[1,0],[1,1]];for i=1:t r=1:length(L);A,B=L[rand(r)],L[rand(r)];A==B?(for j=r L[j]=[L[j],rand(0:1)]end):(push!(L,A$B))end;L)
ML

@ML: Приємно, дякую. Я не думав використовувати термінального оператора. Але вам насправді не потрібні дужки в потрійному вікні, що заощаджує ще 4 ваших пропозицій. Присвоєння Aта Bокремо насправді така ж довжина, як їх присвоєння разом, тому я залишив цю частину такою, якою є. Ще раз дякую за вашу пропозицію!
Олексій А.

Ласкаво просимо. А, бачу. Так, дужки не потрібні.
ML

4

Пітон 2, 141

Я спробував кілька різних методів, але найкраще, що я міг отримати, був відносно простий. Дякуємо @ Sp3000 за 15 годин або близько того (і за те, що я навчав мене про існування int.__xor__).

from random import*
L=[[1,0],[1,1]];C=choice
exec"A=C(L);B=C(L);L=[L+[map(int.__xor__,A,B)],[x+[C([1,0])]for x in L]][A==B];"*input()
print L


4

Пітон 2, 127 122

Якщо припустити, що бітові рядки пітона форми '0b1'тощо є нормальними:

from random import*
C=choice
L=[2,3]
exec"x=C(L)^C(L);L=L+[x]if x else[a*2+C([0,1])for a in L];"*input()
print map(bin,L)

Єдиним м'яким нюансом є використання факту, що XOR (A, B) = 0 iff A = B.

Завдяки @ Sp300 за скорочення forциклу, що вкладається


Однак, дивлячись на коментарі, я думаю, що провідні нулі потрібно зберегти
Sp3000

Я не можу перевірити цю відповідь зараз, але якщо вона не зберігає провідні нулі, вона, на жаль, невірна.
Згарб

3

Піта, 34

u?+RO`TGqJOGKOG+Gsm`s!dqVJKQ[`T`11

Використання зменшується для застосування кожної ітерації. Я поясню, коли закінчу гольф.

Спробуйте тут


2

К, 46 53 46 байт

{x{:[~/t:2?x;{x,*1?2}'x;x,,,/~=/t]}/(1 0;1 1)}

Хороший фрагмент розміру (близько 7 байт) цього полягає в тому, що K не має xor оператора, тому мені довелося реалізувати один сам. Спочатку я використав список рядків, після чого зрозумів, що це шалено дурно. Тому зараз я знову відрізав 7 байт!

Перед:

{x{:[~/t:2?x;{x,*$1?2}'x;x,,,/$~=/(0$')'t]}/$:'10 11}

@JohnE зазначив у коментарях, що початковий стан повинен був бути жорстким кодом, що коштувало 7 зайвих байт. : /


Моє прочитання специфікації проблеми полягає в тому, що ви завжди повинні починати з жорстко закодованого "Всесвіту" (1 0;1 1)- ваша програма сприймає це як вхід.
JohnE

@JohnE Виправлено. Однак немає гарантії, що це спрацює, оскільки я не перевіряв зміни; Я щойно спробував закінчити частину вашого
відбиття

Здається, добре працює і в Коні.
JohnE

2

JavaScript ( ES6) ) 152

Функція, що використовує рядки (з числами вона повинна бути коротшою, але в операціях біт JavaScript обмежена 32-бітовими цілими числами).

Тестуйте у Firefox, використовуючи фрагмент нижче.

F=(t,L=['10','11'],l=2,R=n=>Math.random()*n|0,a=L[R(l)],b=L[R(l)])=>
   t--?a==b
     ?F(t,L.map(x=>x+R(2)),l)
     :F(t,L,L.push([...a].map((x,p)=>x^b[p]).join('')))
  :L
  
test=_=>O.innerHTML=F(+I.value).join('\n')
#I{width:3em}
<input id=I value=10><button onclick=test()>-></button><pre id=O></pre>


1

К, 45 41 38 байт

{x{(x,,~=/t;{x,1?2}'x)@~/t:2?x}/1,'!2}

Структура моєї відповіді досить схожа на структуру @ kirbyfan64sos, але замість рядків я використовував вектори 1/0, і я уникаю необхідності умовного ( :[ ; ; ]), замість того, щоб індексувати у списку.

Кілька пробіжок:

  {x{(x,,~=/t;{x,1?2}'x)@~/t:2?x}/1,'!2}3
(1 0 0 0
 1 1 1 1
 0 1 1 1)

  {x{(x,,~=/t;{x,1?2}'x)@~/t:2?x}/1,'!2}3
(1 0 0
 1 1 0
 0 1 0
 1 0 0)

  {x{(x,,~=/t;{x,1?2}'x)@~/t:2?x}/1,'!2}3
(1 0 0
 1 1 0
 0 1 0
 1 1 0)

Редагувати:

Збережено чотири байти з більш компактним способом побудови початкового Всесвіту:

1,'!2     / new
(1 0;1 1) / old

Edit2:

Я забув, що "вибрати" може вважати список правильним аргументом:

  2?"abcd"
"dc"
  2?"abcd"
"cc"
  2?"abcd"
"ca"

Тож я можу спростити частину цього. Кредит, де це належить, Кірбі отримав цю хитрість ще до мене.

2?x    / new
x@2?#x / old

1
Данг, іноді я думаю, що знаю К, то бачу ваші відповіді ...: O
kirbyfan64sos

Я думаю, що це рішення, безумовно, вважається зусиллями команди!
JohnE

1

Javascript, 241 233 байт

Це якось довго.

a=[[1,0],[1,1]];for(b=prompt();b--;)if(c=a.length,d=a[c*Math.random()|0],e=a[c*Math.random()|0],d+""==e+"")for(f=0;f<c;f++)a[f].push(2*Math.random()|0);else{g=[];for(h=0;h<d.length;h++)g.push(d[h]^e[h]);a.push(g)}alert(a.join("\n"));

Компілятор закриття стиснув його, заощадивши 8 байт.
Густаво Родрігес

216 байт:, for(b=prompt(a=[[1,0],[1,1]]),R=Math.random;b--;){c=a.length;d=a[c*R()|0];e=a[c*R()|0];if(d+""==e+"")for(f=0;f<c;f++)a[f].push(2*R()|0);else{for(h=0,g=[];h<d.length;)g.push(d[h]^e[h++]);a.push(g)}}alert(a.join("\n"))дає бажаний вихід 3/5 часу.
Ісмаїл Мігель

217 байт:, for(b=prompt(a=[[1,0],[1,1]]),R=Math.random;b--;){c=a.length;d=a[c*R()|0];e=a[c*R()|0];if(d+""==e+"")for(f=0;f<c;f++)a[f].push(2*R()|0);else{g=[];for(h=0;h<d.length;h++)g.push(d[h]^e[h]);a.push(g)}}alert(a.join("\n"))працює 90% часу.
Ісмаїл Мігель

1

T-SQL (2012+), 1019

Мені дуже шкода, що це ніде не є конкурентоспроможним, але якщо чесно, я не думав, що зможу це зробити так, щоб працювати, і мені довелося опублікувати це, як тільки я це зробив. Я спробував трохи пограти в гольф :)

Для обробки бінарних / цілих перетворень мені довелося створити пару скалярних функцій (513 байтів). Aпереходить від цілого числа до бітового рядка. Bробить зворотний.

CREATE FUNCTION A(@ BIGINT)RETURNS VARCHAR(MAX)AS
BEGIN
DECLARE @S VARCHAR(MAX);
WITH R AS(SELECT @/2D,CAST(@%2 AS VARCHAR(MAX))M
UNION ALL
SELECT D/2,CAST(D%2 AS VARCHAR(MAX))+M
FROM R
WHERE D>0)SELECT @S=M FROM R WHERE D=0
RETURN @S
END
CREATE FUNCTION B(@ VARCHAR(MAX))RETURNS BIGINT AS
BEGIN
DECLARE @I BIGINT;
WITH R AS(SELECT CAST(RIGHT(@,1)AS BIGINT)I,1N,LEFT(@,LEN(@)-1)S
UNION ALL 
SELECT CAST(RIGHT(S,1)AS BIGINT)*POWER(2,N),N+1,LEFT(S,LEN(S)-1)
FROM R
WHERE S<>''
)SELECT @I=SUM(I)FROM R
RETURN @I
END

Тоді є процедура. @C- кількість кроків

DECLARE @C INT=9
DECLARE @ TABLE(S VARCHAR(MAX))
DECLARE @R VARCHAR(MAX)
INSERT @ VALUES('10'),('11')
WHILE(@C>=0)
BEGIN
SET @C-=1
SELECT @R=CASE WHEN MAX(S)=MIN(S)THEN''ELSE RIGHT(REPLICATE('0',99)+dbo.A(dbo.B(MAX(S))^dbo.B(MIN(S))),LEN(MAX(S)))END
FROM(SELECT TOP 2S,ROW_NUMBER()OVER(ORDER BY(SELECT\))N FROM @,(VALUES(1),(1),(1))D(D)ORDER BY RAND(CAST(NEWID()AS VARBINARY(50))))A
IF @R=''UPDATE @ SET S=CONCAT(S,ROUND(RAND(CAST(NEWID() AS VARBINARY(50))),0))
ELSE INSERT @ VALUES(@R)
END
SELECT * FROM @

Десять тисяч ітерацій зайняли близько 2 хвилин і повернули 9991 рядок

1001001100110
1101001001110
0111100100101
1111100001011
1111001010011
0110101001101
...
1110101000100
1111011101100
1100001100010
0110010001001
1110100010100


0

Математика, 106 байт

Nest[If[Equal@@#,Map[#~Append~RandomInteger[]&],Append[BitXor@@#]]&[#~RandomChoice~2]@#&,{{1,0},{1,1}},#]&

0

Перл, 102

#!perl -p
@l=qw(10 11);$_=$l[rand@l]^$l[rand@l],$_|=y//0/cr,@l=/1/?(@l,$_):map{$_.~~rand 2}@l for 1..$_;$_="@l"

Спробуй мене .


0

R, 186

L=list(0:1,c(1,1))
if(t>0)for(t in 1:t){A=sample(L,1)[[1]]
B=sample(L,1)[[1]]
if(all(A==B)){L=lapply(L,append,sample(0:1, 1))}else{L=c(L,list(as.numeric(xor(A,B))))}}
L

Нічого магічного тут немає. Введіть значення для tконсолі R та запустіть сценарій. "Гольф" код R важко, але ось більш читабельна версія:

L <- list(0:1, c(1, 1))
if(t > 0) {
  for(t in 1:t) {
    A <- sample(L, 1)[[1]]
    B <- sample(L, 1)[[1]]
    if (all(A == B)) {
      L <- lapply(L, append, sample(0:1, 1))
    } else {
      L <- c(L,list(as.numeric(xor(A, B))))
    }
  }
}
L

Ви можете зберегти ряд символів, призначивши sampleзмінну. наприклад s=sample, тоді використовуйте s, а не зразок. На жаль, я думаю, що ваш метод додавання випадкового біта у lapplyзаповіті призведе до того, що до всіх елементів у списку буде доданий один випадковий зразок. lapply(L,function(x)append(x,sample(0:1,1)))здається, працює, але ціною. Ви можете замінити вас as.numericтим, 1*що має отримати трохи назад.
MickyT

Хороший улов в обох очках, а також приємний трюк примусу
shadowtalker

Також щойно помітив, що ваш рахунок вийшов. Я роблю це 168, використовуючи це
MickyT

0

Рубі, 82

Досить прямо-прямо. Порівняно з іншими мовами для гольфу, рубін, здається, добре поєднується зі своєю великою стандартною бібліотекою.

->t{l=[2,3]
t.times{a,b=l.sample 2
a.equal?(b)?l.map!{|x|x*2+rand(2)}:l<<(a^b)}
l}

Вибірка вибірки для t = 101010:

[9, 15, 6, 13, 5, 12, 10, 11, 5, 4, 15, 13, 2, 7, 11, 9, 3, 3, 8, 6, 3, 13, 13, 12, 10, 9, 2, 4, 14, 9, 9, 14, 15, 7, 10, 4, 10, 14, 13, 7, 15, 7]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.