Index finite lists of positive integers: Difference between revisions
Content added Content deleted
m (fixed an HTML tag.) |
(→{{header|Go}}: cleanups. handle empty list, return errors rather than panic, add output showing empty list and errors.) |
||
Line 58: | Line 58: | ||
) |
) |
||
// |
// Prepend base 10 representation with an "a" and you get a base 11 number. |
||
// Unfortunately base 11 is a little awkward with big.Int, so just treat it |
// Unfortunately base 11 is a little awkward with big.Int, so just treat it |
||
// as base 16. |
|||
func rank(l []big.Int) |
func rank(l []big.Int) (r big.Int, err error) { |
||
if len(l) == 0 { |
|||
⚫ | |||
⚫ | |||
s := make([]string, len(l)) |
s := make([]string, len(l)) |
||
for i, n := range l { |
for i, n := range l { |
||
ns := n.String() |
|||
if ns[0] == '-' { |
|||
⚫ | |||
return r, fmt.Errorf("negative integers not mapped") |
|||
⚫ | |||
} |
|||
s[i] = "a" + ns |
|||
} |
} |
||
⚫ | |||
return |
return |
||
} |
} |
||
// Split the base 16 representation at "a", recover the base 10 numbers. |
// Split the base 16 representation at "a", recover the base 10 numbers. |
||
func unrank(r |
func unrank(r big.Int) ([]big.Int, error) { |
||
s16 := fmt.Sprintf("%x", &r) |
|||
switch { |
|||
case s16 == "0": |
|||
return nil, nil // empty list |
|||
case s16[0] != 'a': |
|||
return nil, fmt.Errorf("unrank not bijective") |
|||
} |
|||
s := strings.Split(s16[1:], "a") |
|||
l := make([]big.Int, len(s)) |
l := make([]big.Int, len(s)) |
||
for i, s1 := range s { |
for i, s1 := range s { |
||
_, ok := l[i].SetString(s1, 10) |
if _, ok := l[i].SetString(s1, 10); !ok { |
||
return nil, fmt.Errorf("unrank not bijective") |
|||
⚫ | |||
panic("really") |
|||
} |
} |
||
} |
} |
||
return l |
return l, nil |
||
} |
} |
||
func main() { |
func main() { |
||
// show empty list |
|||
var l []big.Int |
|||
⚫ | |||
⚫ | |||
⚫ | |||
fmt.Println("Empty list:", l, &r, u) |
|||
// show random list |
|||
l = random() |
|||
r, _ = rank(l) |
|||
u, _ = unrank(r) |
|||
⚫ | |||
for _, n := range l { |
for _, n := range l { |
||
fmt.Println(" ", &n) |
fmt.Println(" ", &n) |
||
} |
} |
||
⚫ | |||
fmt.Println("Rank:") |
fmt.Println("Rank:") |
||
fmt.Println(" ", r) |
fmt.Println(" ", &r) |
||
⚫ | |||
fmt.Println("Unranked:") |
fmt.Println("Unranked:") |
||
for _, n := range u { |
for _, n := range u { |
||
fmt.Println(" ", &n) |
fmt.Println(" ", &n) |
||
} |
} |
||
// show error with list containing negative |
|||
var n big.Int |
|||
n.SetInt64(-5) |
|||
_, err := rank([]big.Int{n}) |
|||
fmt.Println("\nList element:", &n, err) |
|||
// show technique is not bijective |
|||
n.SetInt64(1) |
|||
_, err = unrank(n) |
|||
fmt.Println("Rank:", &n, err) |
|||
} |
} |
||
// returns |
// returns 0 to 5 numbers in the range 1 to 2^100 |
||
func random() []big.Int { |
func random() []big.Int { |
||
r := rand.New(rand.NewSource(time.Now().Unix())) |
r := rand.New(rand.NewSource(time.Now().Unix())) |
||
l := make([]big.Int, |
l := make([]big.Int, r.Intn(6)) |
||
one := big.NewInt(1) |
one := big.NewInt(1) |
||
max := new(big.Int).Lsh(one, 100) |
max := new(big.Int).Lsh(one, 100) |
||
Line 114: | Line 143: | ||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Empty list: [] 0 [] |
|||
List: |
List: |
||
170245492534662309353778826165 |
|||
250046378143152073779399139308 |
|||
82227712638678862510272817700 |
|||
433677733115839140356036818773 |
|||
709681404405498840918712626000 |
|||
Rank: |
Rank: |
||
17827272030291729487097780664374477811820701746650470453292650775464474368 |
|||
86898591846547743089837040293705765764160568618712035006919317223922729203294339688481288514295259746298650624 |
|||
Unranked: |
Unranked: |
||
170245492534662309353778826165 |
|||
250046378143152073779399139308 |
|||
82227712638678862510272817700 |
|||
433677733115839140356036818773 |
|||
709681404405498840918712626000 |
|||
List element: -5 negative integers not handled |
|||
Rank: 1 unrank not bijective |
|||
</pre> |
</pre> |
||