Index finite lists of positive integers: Difference between revisions

Content added Content deleted
(→‎{{header|Go}}: cleanups. handle empty list, return errors rather than panic, add output showing empty list and errors.)
(→‎{{header|Go}}: add bijective solution)
Line 48: Line 48:


=={{header|Go}}==
=={{header|Go}}==
'''Bijective'''

A list element n is encoded as a 1 followed by n 0's. Element encodings are concatenated to form a single integer rank. An advantage of this encoding is that no special case is required to handle the empty list.
<lang go>package main

import (
"fmt"
"math/big"
)

func rank(l []uint) (r big.Int) {
for _, n := range l {
r.Lsh(&r, n+1)
r.SetBit(&r, int(n), 1)
}
return
}

func unrank(n big.Int) (l []uint) {
m := new(big.Int).Set(&n)
for a := m.BitLen(); a > 0; {
m.SetBit(m, a-1, 0)
b := m.BitLen()
l = append(l, uint(a-b-1))
a = b
}
return
}

func main() {
var b big.Int
for i := 0; i <= 10; i++ {
b.SetInt64(int64(i))
u := unrank(b)
r := rank(u)
fmt.Println(i, u, &r)
}
b.SetString("12345678901234567890", 10)
u := unrank(b)
r := rank(u)
fmt.Printf("\n%v\n%d\n%d\n", &b, u, &r)
}</lang>
{{out}}
<pre>
0 [] 0
1 [0] 1
2 [1] 2
3 [0 0] 3
4 [2] 4
5 [1 0] 5
6 [0 1] 6
7 [0 0 0] 7
8 [3] 8
9 [2 0] 9
10 [1 1] 10

12345678901234567890
[1 1 1 0 1 1 1 2 1 1 2 0 3 0 2 0 0 1 1 0 3 0 0 0 0 4 1 1 0 1 2 1]
12345678901234567890
</pre>
'''Alternative'''

A bit of a hack to make a base 11 number then interpret it as base 16, just because that's easiest. Not bijective. Practical though for small lists of large numbers.
<lang go>package main
<lang go>package main