Related but different.
Taken from the book: Marvin Minsky 1967 – Computation:
Finite and Infinite Machines, chapter 14.
Background
As the Gödel proved, it is possible to encode with a unique positive integer not just any string
but any list structure, with any level of nesting.
Procedure of encoding \$G(x)\$ is defined inductively:
- If \$x\$ is a number, \$G(x) = 2^x\$
- If \$x\$ is a list \$[n_0, n_1, n_2, n_3, ...]\$, \$G(x) = 3^{G(n_0)} \cdot 5^{G(n_1)} \cdot 7^{G(n_2)} \cdot 11^{G(n_3)} \cdot...\$
Bases are consecutive primes.
Examples:
[0] → 3
[[0]] → \3ドル^3 =\$ 27
[1, 2, 3] → \3ドル^{2^1} \cdot 5^{2^2} \cdot 7^{2^3} = \$
32427005625
[[0, 1], 1] → \3ドル^{3^{2^0} \cdot 5^{2^1}} \cdot 5^{2^1} = \$
15206669692833942727992099815471532675
Task
Create a program that encoding (in this way) any given (possibly ragged) list to integer number.
This is code-golf, so the shortest code in bytes wins.
Input
Valid non-empty list.
UPD
Some considerations regarding empty lists are given here.
You may assume:
- There are no empty sublists
- Structure is not broken (all parentheses are paired)
- List contains only non-negative integers
Output
Positive integer obtained by the specified algorithm
Note
Numbers can be very large, be careful! Your code must be correct in principle, but it is acceptable that it cannot print some number. However, all test cases are checked for TIO with Mathematica program and work correctly.
Test cases
[0,0,0,0,0] → 15015
[1, 1, 1] → 11025
[[1], [1]] → 38443359375
[0, [[0]], 0] → 156462192535400390625
[[[0], 0], 0] → 128925668357571406980580744739545891609191243761536322527975268535
18 Answers 18
Jelly, (削除) 11 10 9 (削除ここまで) 8 bytes
-1 thanks to Unrelated String! (Use of a dyadic chain in place of a monadic compound link avoiding the need for argument manipulation with `.)
߀Żð%¡ÆẸ
A monadic Link that accepts a ragged list of non-negative integers and yields its Gödel encoding.
Try it online! Or see the test-suite.
How?
߀Żð%¡ÆẸ - Link: non-empty list OR number, X
¡ - repeat...
% - ...number of times: (X) modulo (X)
positive ints -> 0
zero -> nan*
non-empty lists -> non-empty lists*
* truthy non-integers are treated by ¡ as 1
ð - ...action: the dyadic chain - f(X, X):
€ - for each E in X:
ß - call this Link with X=E
Ż - prefix with a zero (if X=zero we get [0])
ÆẸ - recompose from prime exponent list
e.g.:
[0,4,0,2] -> 3^4 ×ばつ 7^2 = 3969
[0] -> 2^0 = 1
n -> 2^n (non-list n treated as [n])
-
1\$\begingroup\$ 8 with
ð\$\endgroup\$Unrelated String– Unrelated String2023年04月12日 09:41:11 +00:00Commented Apr 12, 2023 at 9:41 -
2\$\begingroup\$ Pesky
`:) thanks @UnrelatedString \$\endgroup\$Jonathan Allan– Jonathan Allan2023年04月12日 16:35:51 +00:00Commented Apr 12, 2023 at 16:35
Brachylog, 24 bytes
;2^(|↰mGl~l×ばつ
Surely there are shorter ways to generate a list of primes...
Brachylog is based on SWI-Prolog and can deal with arbitrarily large integers, but this will quickly run out of memory for even simple lists.
Explanation
;2^( Output = 2^Input
| Or (if the input is not an integer)
↰mG Recursive call of this predicate for all elements of the Input; call the result G
Gl~l Take a list with as many elements as G
N3mṗm≠≜ It must be a list of primes greater than 3 and all different (it always unifies with increasing magnitudes)
;Gz Zip with G
^m Map power
×ばつ Multiply
Vyxal, A (削除) 23 (削除ここまで) (削除) 21 (削除ここまで) 11 bytes
@AndrovT cool result:
Eλ-[żǎ$vxeΠ
Unfortunately, can't explain in detail. Hope one of Vyxal' experts helps...
My old version, maybe useful for beginners in Vyxal:
ƛIȧ[:L›ÞpŻ$vx ̈£e|E]fΠ
Every input must be list of lists, so first test case should be [[1, 1, 1]] etc.
-2 bytes thanks @emanresu (Vyxal chat)
ƛ #Begin lambda map Iȧ #Condition for If: is it list? [ #Begin If :L› #If list - get length and add 1 ÞpŻ #Get slice of given length from infinite list of primes $ #Swap vx #Recursively apply to list ̈£e #Zip and reduce pairs with exponentiation | #Else E #If number - two power ] #End If and lambda map, fΠ #Flatten and reduce by product
-
1
-
\$\begingroup\$ @AndrovT Cool, thanks! You should post your own answer! Or, please explain, how
Πworks correct without closed]? \$\endgroup\$lesobrod– lesobrod2023年04月13日 03:50:23 +00:00Commented Apr 13, 2023 at 3:50 -
\$\begingroup\$ there's no need to close structures in vyxal \$\endgroup\$AndrovT– AndrovT2023年04月13日 13:31:50 +00:00Commented Apr 13, 2023 at 13:31
R, (削除) 103 (削除ここまで) (削除) 102 (削除ここまで) 98 bytes
Edit: -1 byte, and then -4 more, both thanks to pajonk
`?`=\(x,p=3)`if`(sum(!p%%1:p)>2,x?p+1,`if`(is.list(x),`if`(length(x),(x[-1]?p+1)*p^?el(x),1),2^x))
-
1\$\begingroup\$ You've got an unnecessary newline at the end, I think. \$\endgroup\$pajonk– pajonk2023年04月13日 12:03:11 +00:00Commented Apr 13, 2023 at 12:03
-
\$\begingroup\$ @pajonk - Oh, thanks for spotting that! \$\endgroup\$Dominic van Essen– Dominic van Essen2023年04月13日 12:05:05 +00:00Commented Apr 13, 2023 at 12:05
-
1\$\begingroup\$ Another -1:
x[[1]]->el(x)\$\endgroup\$pajonk– pajonk2023年04月13日 12:09:44 +00:00Commented Apr 13, 2023 at 12:09 -
1
-
\$\begingroup\$ @pajonk - Thanks again! \$\endgroup\$Dominic van Essen– Dominic van Essen2023年04月13日 16:09:39 +00:00Commented Apr 13, 2023 at 16:09
JavaScript (ES13), 82 bytes
Expects a ragged list of Bigints. Returns a Bigint.
f=(a,k=2n,t=1n)=>a.at?a.map(a=v=>(g=d=>k%d--?g(d):d)(k++)?a(v):t*=k**f(v))&&t:k**a
Or 79 bytes without Bigints.
Arturo, 66 bytes
f:$[x][(block? x)?[p:3∏map x=>[p^f&until->prime? p->'p+2]]->2^x]
f:$[x][ ; a function f taking an argument x
(block? x)?[ ; is x a block? then...
p:3 ; assign 3 to p
∏ ; product
map x=>[ ; map over x, assign current elt to &
p^f& ; p raised to the Gödel encoding of the current elt
until->prime? p-> ; until p is prime...
'p+2 ; add 2 to p via in-place modification
] ; end map
] ; end the 'true' part of the ternary
->2^x ; ...otherwise, if x isn't a block, take 2^x
] ; end function
-
\$\begingroup\$ Interesting fresh and bright language! \$\endgroup\$lesobrod– lesobrod2023年04月11日 19:19:45 +00:00Commented Apr 11, 2023 at 19:19
Python, 103 bytes
g=lambda n,k=1,m=1:m%k>n or-~g(n,k+1,m*k)
f=lambda l,p=3:l*0==0and 2**l or p**f(l[0])*f(l[1:]or 0,g(p))
Method for calculating next prime is shamelessly adapted from Dennis's answer.
PARI/GP, 118 bytes
Modified from @Dominic van Essen's answer
Golfed version, try it online!
G(x,p=3)={if(sum(i=1,p,(p%i)==0)>2,G(x,p+1),if(type(x)=="t_VEC",if(#x,p^G(x[1])*G(vector(#x-1,i,x[i+1]),p+1),1),2^x))}
Ungolfed version
G(x, p = 3) =
{
if (sum(i = 1, p, (p % i) == 0) > 2,
G(x, p + 1),
if (type(x) == "t_VEC",
if (#x,
p^G(x[1]) * G(vector(#x - 1, i, x[i + 1]), p + 1),
1
),
2^x
)
)
}
print(G(0)) \\ 1
print(G(1)) \\ 2
print(G([0,0])) \\ 15
print(G([0,1])) \\ 75
print(G([0])) \\ 3
print(G([[0]])) \\ 27
print(G([0,0,0,0,0])) \\ 15015
print(G([1,2,3])) \\ 32427005625
print(G([[0,1],1])) \\ 15206669692833942727992099815471532675
Julia, (削除) 68 (削除ここまで) 66 bytes
!x::Int=2^x
!(x,p=2)=prod(i->(while(p+=1).%(2:p-1)∋0end;p^!i),x)
-2 bytes by MarcMush.
Doesn't use prime built-ins, which are not in Base anyway. Feels a bit weird to include a type annotation while golfing in a language that doesn't require it, but it looks like a decent way to disambiguate between numbers and lists.
Note that this will only produce correct output within Int64. At the expense of 5 bytes, we can add a big(...) wrapper to get a version that processes all test cases as desired:
Julia, (削除) 73 (削除ここまで) 71 bytes
!x::Int=big(2)^x
!(x,p=2)=prod(i->(while(p+=1).%(2:p-1)∋0end;p^!i),x)
-
\$\begingroup\$ Kirill L. in fact program could accept single numbers. This is not quite clear point, but you can exclude special detection for numbers \$\endgroup\$lesobrod– lesobrod2023年04月22日 14:18:57 +00:00Commented Apr 22, 2023 at 14:18
-
\$\begingroup\$ @lesobrod Thanks, I've updated the answer to use the shorter version as the "default" one. \$\endgroup\$Kirill L.– Kirill L.2023年04月22日 15:52:32 +00:00Commented Apr 22, 2023 at 15:52
-
1\$\begingroup\$ I didn't try it but
prod(f,x)might be shorter thanprod(x.|>f)? \$\endgroup\$MarcMush– MarcMush2023年04月22日 23:15:55 +00:00Commented Apr 22, 2023 at 23:15 -
\$\begingroup\$ @MarcMush It works indeed, thanks! \$\endgroup\$Kirill L.– Kirill L.2023年04月23日 07:39:16 +00:00Commented Apr 23, 2023 at 7:39
05AB1E, (削除) 23 (削除ここまで) 19 bytes
o"Ddië®δ.VāØsmP"©.V
Also works for loose integer inputs, instead of just (ragged) lists.
Try it online or verify all test cases.
Explanation:
Recursive functions are always so verbose in 05AB1E.. :/
o # Take 2 to the power each inner-most integer of the (implicit) input
"..." # Push the recursive string explained below
© # Store it in variable `®`
.V # Evaluate and execute it as 05AB1E code
# (after which the result is output implicitly)
D # Duplicate the current list
di # If it's a single integer:
# (do nothing, simply keep it as is)
ë # Else (it's a list instead):
δ # Map over each inner item:
® .V # Do a recursive call
ā # Then push a list in the range [1,length] (without popping)
Ø # Map index each to the 0-based prime: [3,5,7,...]
s # Swap the two lists on the stack
m # Take the primes to the power of the values
P # Take the product of this list
Charcoal, 67 bytes
×ばつXζ⊟+⟦0⟧κη»⊞ιη»I⊟θ
Try it online! Link is to verbose version of code. Explanation:
≔X2Aθ
Vectorised raise 2 to the power of the input.
⊞υθFυFΦι+⟦⟧κ⊞υκF⮌υ«
Extract all of the sublists and loop over them in reverse.
≔1η≔2ζ
Start with a product of 1 and a last prime of 2.
Fι«
Loop over the elements of the list.
≦⊕ζW¬⬤...2ζ%ζμ≦⊕ζ
Get the next prime number by trial division (1 byte shorter than Wilson's theorem).
×ばつXζ⊟+⟦0⟧κη»
Multiply the product by the prime power of the next list element (but if that's a list, then use its last element, as that's where we put the value on a previous loop iteration).
⊞ιη
Save the resulting value to the sublist.
»I⊟θ
Output the resulting value of the original list.
Pyth, 23 bytes
L?sIb^2b*F^V.fP_Zlb3yMb
Defines an encoding function y(b).
Explanation
L # define y(b)
?sIb # if b is invariant under s: (sums for list, int for int)
^2b # 2 ^ b
# else:
yMb # apply y to each element of b
.fP_Zlb3 # generate a list of len(b) primes starting with 3
^V # vectorized exponentiation
*F # fold over multiplication
-
\$\begingroup\$ woah. great ! respect \$\endgroup\$Jane– Jane2023年04月12日 14:35:39 +00:00Commented Apr 12, 2023 at 14:35
Wolfram Language (Mathematica), 37 bytes
1##&@@(i=1;Prime@++i^#&/@#)&//@(2^#)&
(2^#) numbers: x -> 2^x
//@ lists:
1##&@@( /@#) product of
i=1;Prime@++i^#& prime(n+1)^x_n
PowerShell Core, 147 bytes
$f={$r,$p=1,2
$args|%{do{$p++;for($u,$k=1,0;++$u-$p){$k+=!($p%$u)}}while($k)$r=$r*($b=[bigint])::Pow($p,(&($f,{$b::Pow(2,$_)})[$_-is[int]]@_))}
$r}
Fun challenge!
Recursive function that expects the input list using splatting and returns a [bigint]
Please ignore the inconsistent output of the array in the tests result as PowerShell has a tendency to flatten them sometime.
Explanation
This part updates $p to become the next prime after $p
do{$p++;for($u,$k=1,0;++$u-$p){$k+=!($p%$u)}}while($k)
This part checks whether the current list item $_ is a number or not
If it is a number, we take its power of two, otherwise, we do a recursive call.
$r=$r*($b=[bigint])::Pow($p,(&($f,{$b::Pow(2,$_)})[$_-is[int]]@_))}
Wolfram Language (Mathematica), 71 bytes
Of course, answering your own challenge is a bit ridiculous, but it is rather a supplement to not break the main post.
Thanks @PaŭloEbermann for the idea!
It seems we can account for the empty lists, naively but correctly, using the next encoding:
- If \$x\$ is non-negative integer, \$G(x) = 2^{x+1}\$
- If \$x\$ is an empty list,
[ ], \$G(x) = 2^0 = 1\$ - If \$x\$ is a list, \$[n_0, n_1, n_2, n_3, ...], G(x) = 3^{G(n_0)} \cdot 5^{G(n_1)} \cdot 7^{G(n_2)} \cdot 11^{G(n_3)} \cdot...\$
Of course, this is a purely intuitive idea without proof. But I do not see contradictions at the moment.
So here is Mathematica program that encodes any array-like structure (with possible empty lists) with a unique positive integer.
Switch[#,{},1,{__},Times@@(Prime@Range[2,Length@#+1]^#0/@#),_,2^(#+1)]&
Some related test cases:
[] → 1
[[]] → 3
[[], 1, []] → 13125
[[], [0, []], 1] → 204721573027200065553188323974609375
Explore related questions
See similar questions with these tags.
1? Ah, that would be the same as the encoding of the number0. \$\endgroup\$