Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
2
Task/Minimal-steps-down-to-1/00-META.yaml
Normal file
2
Task/Minimal-steps-down-to-1/00-META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Minimal_steps_down_to_1
|
||||
45
Task/Minimal-steps-down-to-1/00-TASK.txt
Normal file
45
Task/Minimal-steps-down-to-1/00-TASK.txt
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
Given:
|
||||
* A starting, positive integer (greater than one), N.
|
||||
* A selection of possible integer perfect divisors, D.
|
||||
* And a selection of possible subtractors, S.
|
||||
The goal is find the minimum number of steps necessary to reduce N down to one.
|
||||
|
||||
At any step, the number may be:
|
||||
* Divided by any member of D if it is perfectly divided by D, (remainder zero).
|
||||
* OR have one of S subtracted from it, if N is greater than the member of S.
|
||||
|
||||
|
||||
There may be many ways to reduce the initial N down to 1. Your program needs to:
|
||||
* Find the ''minimum'' number of ''steps'' to reach 1.
|
||||
* Show '''one''' way of getting fron N to 1 in those minimum steps.
|
||||
<br>
|
||||
;Examples:
|
||||
No divisors, D. a single subtractor of 1.
|
||||
:Obviousely N will take N-1 subtractions of 1 to reach 1
|
||||
|
||||
Single divisor of 2; single subtractor of 1:
|
||||
:N = 7 Takes 4 steps N -1=> 6, /2=> 3, -1=> 2, /2=> 1
|
||||
:N = 23 Takes 7 steps N -1=>22, /2=>11, -1=>10, /2=> 5, -1=> 4, /2=> 2, /2=> 1
|
||||
|
||||
Divisors 2 and 3; subtractor 1:
|
||||
:N = 11 Takes 4 steps N -1=>10, -1=> 9, /3=> 3, /3=> 1
|
||||
|
||||
;Task:
|
||||
Using the possible divisors D, of 2 and 3; together with a possible subtractor S, of 1:
|
||||
|
||||
:1. Show the number of steps and possible way of diminishing the numbers 1 to 10 down to 1.
|
||||
:2. Show a count of, and the numbers that: have the maximum minimal_steps_to_1, in the range 1 to 2,000.
|
||||
|
||||
Using the possible divisors D, of 2 and 3; together with a possible subtractor S, of 2:
|
||||
|
||||
:3. Show the number of steps and possible way of diminishing the numbers 1 to 10 down to 1.
|
||||
:4. Show a count of, and the numbers that: have the maximum minimal_steps_to_1, in the range 1 to 2,000.
|
||||
|
||||
|
||||
;Optional stretch goal:
|
||||
:2a, and 4a: As in 2 and 4 above, but for N in the range 1 to 20_000
|
||||
|
||||
|
||||
;Reference:
|
||||
* [https://www.youtube.com/watch?v=f2xi3c1S95M Learn Dynamic Programming (Memoization & Tabulation)] Video of similar task.
|
||||
|
||||
52
Task/Minimal-steps-down-to-1/11l/minimal-steps-down-to-1.11l
Normal file
52
Task/Minimal-steps-down-to-1/11l/minimal-steps-down-to-1.11l
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
T Mintab
|
||||
Set[Int] divs, subs
|
||||
[Int] table
|
||||
[[String]] hows
|
||||
|
||||
F (divs, subs)
|
||||
.divs = copy(divs)
|
||||
.subs = copy(subs)
|
||||
|
||||
F _mintab(n)
|
||||
‘Tabulation, memoised minimised steps to 1’
|
||||
V table = [n + 2] * (n + 1)
|
||||
table[1] = 0
|
||||
V how = (0 .< n + 2).map(_ -> [‘’])
|
||||
how[1] = [String(‘=’)]
|
||||
L(t) 1 .< n
|
||||
V thisplus1 = table[t] + 1
|
||||
L(d) .divs
|
||||
V dt = d * t
|
||||
I dt <= n & thisplus1 < table[dt]
|
||||
table[dt] = thisplus1
|
||||
how[dt] = how[t] [+] [‘/#.=>#2’.format(d, t)]
|
||||
L(s) .subs
|
||||
V st = s + t
|
||||
I st <= n & thisplus1 < table[st]
|
||||
table[st] = thisplus1
|
||||
how[st] = how[t] [+] [‘-#.=>#2’.format(s, t)]
|
||||
.table = table
|
||||
.hows = how.map(h -> reversed(h)[0 .< (len)-1])
|
||||
R (.table, .hows)
|
||||
|
||||
F ()(n)
|
||||
‘Tabulation’
|
||||
V (table, hows) = ._mintab(n)
|
||||
R (table[n], hows[n])
|
||||
|
||||
L(DIVS, SUBS) [([2, 3], [1]), ([2, 3], [2])]
|
||||
print("\nMINIMUM STEPS TO 1: Tabulation algorithm")
|
||||
print(‘ Possible divisors: ’DIVS)
|
||||
print(‘ Possible decrements: ’SUBS)
|
||||
V mintab = Mintab(Set(DIVS), Set(SUBS))
|
||||
mintab(10)
|
||||
L(n) 1..10
|
||||
V (steps, how) = (mintab.table[n], mintab.hows[n])
|
||||
print(‘ mintab(#2) in #2 by: ’.format(n, steps)‘ ’how.join(‘, ’))
|
||||
|
||||
L(upto) [2000, 50'000]
|
||||
mintab(upto)
|
||||
print("\n Those numbers up to "upto‘ that take the maximum, "minimal steps down to 1":’)
|
||||
V mx = max(mintab.table[1..])
|
||||
V ans = enumerate(mintab.table).filter((n, steps) -> steps == @mx).map((n, steps) -> n)
|
||||
print(‘ Taking ’mx‘ steps is/are the ’ans.len‘ numbers: ’ans.map(n -> String(n)).join(‘, ’))
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public static class MinimalSteps
|
||||
{
|
||||
public static void Main() {
|
||||
var (divisors, subtractors) = (new int[] { 2, 3 }, new [] { 1 });
|
||||
var lookup = CreateLookup(2_000, divisors, subtractors);
|
||||
Console.WriteLine($"Divisors: [{divisors.Delimit()}], Subtractors: [{subtractors.Delimit()}]");
|
||||
PrintRange(lookup, 10);
|
||||
PrintMaxMins(lookup);
|
||||
lookup = CreateLookup(20_000, divisors, subtractors);
|
||||
PrintMaxMins(lookup);
|
||||
Console.WriteLine();
|
||||
|
||||
subtractors = new [] { 2 };
|
||||
lookup = CreateLookup(2_000, divisors, subtractors);
|
||||
Console.WriteLine($"Divisors: [{divisors.Delimit()}], Subtractors: [{subtractors.Delimit()}]");
|
||||
PrintRange(lookup, 10);
|
||||
PrintMaxMins(lookup);
|
||||
lookup = CreateLookup(20_000, divisors, subtractors);
|
||||
PrintMaxMins(lookup);
|
||||
}
|
||||
|
||||
private static void PrintRange((char op, int param, int steps)[] lookup, int limit) {
|
||||
for (int goal = 1; goal <= limit; goal++) {
|
||||
var x = lookup[goal];
|
||||
if (x.param == 0) {
|
||||
Console.WriteLine($"{goal} cannot be reached with these numbers.");
|
||||
continue;
|
||||
}
|
||||
Console.Write($"{goal} takes {x.steps} {(x.steps == 1 ? "step" : "steps")}: ");
|
||||
for (int n = goal; n > 1; ) {
|
||||
Console.Write($"{n},{x.op}{x.param}=> ");
|
||||
n = x.op == '/' ? n / x.param : n - x.param;
|
||||
x = lookup[n];
|
||||
}
|
||||
Console.WriteLine("1");
|
||||
}
|
||||
}
|
||||
|
||||
private static void PrintMaxMins((char op, int param, int steps)[] lookup) {
|
||||
var maxSteps = lookup.Max(x => x.steps);
|
||||
var items = lookup.Select((x, i) => (i, x)).Where(t => t.x.steps == maxSteps).ToList();
|
||||
Console.WriteLine(items.Count == 1
|
||||
? $"There is one number below {lookup.Length-1} that requires {maxSteps} steps: {items[0].i}"
|
||||
: $"There are {items.Count} numbers below {lookup.Length-1} that require {maxSteps} steps: {items.Select(t => t.i).Delimit()}"
|
||||
);
|
||||
}
|
||||
|
||||
private static (char op, int param, int steps)[] CreateLookup(int goal, int[] divisors, int[] subtractors)
|
||||
{
|
||||
var lookup = new (char op, int param, int steps)[goal+1];
|
||||
lookup[1] = ('/', 1, 0);
|
||||
for (int n = 1; n < lookup.Length; n++) {
|
||||
var ln = lookup[n];
|
||||
if (ln.param == 0) continue;
|
||||
for (int d = 0; d < divisors.Length; d++) {
|
||||
int target = n * divisors[d];
|
||||
if (target > goal) break;
|
||||
if (lookup[target].steps == 0 || lookup[target].steps > ln.steps) lookup[target] = ('/', divisors[d], ln.steps + 1);
|
||||
}
|
||||
for (int s = 0; s < subtractors.Length; s++) {
|
||||
int target = n + subtractors[s];
|
||||
if (target > goal) break;
|
||||
if (lookup[target].steps == 0 || lookup[target].steps > ln.steps) lookup[target] = ('-', subtractors[s], ln.steps + 1);
|
||||
}
|
||||
}
|
||||
return lookup;
|
||||
}
|
||||
|
||||
private static string Delimit<T>(this IEnumerable<T> source) => string.Join(", ", source);
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
Dim Shared As Integer minPasos 'minimal number of steps to get to 1
|
||||
Dim Shared As Integer Subtractor '1 or 2
|
||||
Dim Shared As Integer Ns(20000), Ops(20000), MinNs(20000), MinOps(20000)
|
||||
|
||||
Sub Reduce(N As Integer, Paso As Integer) 'Reduce N to 1, recording minimum steps
|
||||
If N = 1 Then
|
||||
If Paso < minPasos Then
|
||||
For i As Integer = 0 To Paso-1
|
||||
MinOps(i) = Ops(i)
|
||||
MinNs(i) = Ns(i)
|
||||
Next i
|
||||
minPasos = Paso
|
||||
End If
|
||||
End If
|
||||
If Paso >= minPasos Then Exit Sub 'don't search further
|
||||
If N Mod 3 = 0 Then Ops(Paso) = 3 : Ns(Paso) = N/3 : Reduce(N/3, Paso+1)
|
||||
If N Mod 2 = 0 Then Ops(Paso) = 2 : Ns(Paso) = N/2 : Reduce(N/2, Paso+1)
|
||||
Ops(Paso) = -Subtractor
|
||||
Ns(Paso) = N-Subtractor
|
||||
Reduce(N-Subtractor, Paso+1)
|
||||
End Sub
|
||||
|
||||
Sub ShowSteps(N As Integer) 'Show minimal steps and how N steps to 1
|
||||
minPasos = 50000
|
||||
Reduce(N, 0)
|
||||
Print "N = " & N & " takes " & minPasos & " steps: N";
|
||||
For i As Integer = 0 To minPasos-1
|
||||
Print Iif(Sgn(MinOps(i)) < 0, " -", " /");
|
||||
Print Abs(MinOps(i)) & "=>" & MinNs(i); '" "
|
||||
Next i
|
||||
Print
|
||||
End Sub
|
||||
|
||||
Sub ShowCount(Range As Integer) 'Show count of maximum minimal steps and their Ns
|
||||
Dim As Integer N, MaxSteps
|
||||
MaxSteps = 0 'find maximum number of minimum steps
|
||||
For N = 1 To Range
|
||||
minPasos = 50000
|
||||
Reduce(N, 0)
|
||||
If minPasos > MaxSteps Then MaxSteps = minPasos
|
||||
Next N
|
||||
Print "Maximum steps:"; MaxSteps; " for N =";
|
||||
For N = 1 To Range 'show numbers (Ns) for Maximum steps
|
||||
minPasos = 50000
|
||||
Reduce(N, 0)
|
||||
If minPasos = MaxSteps Then Print N; '" ";
|
||||
Next N
|
||||
Print
|
||||
End Sub
|
||||
|
||||
Dim As Integer N
|
||||
Subtractor = 1 '1.
|
||||
For N = 1 To 10
|
||||
ShowSteps(N)
|
||||
Next N
|
||||
ShowCount(2000) '2.
|
||||
ShowCount(20000) '2a.
|
||||
|
||||
Print
|
||||
Subtractor = 2 '3.
|
||||
For N = 1 To 10
|
||||
ShowSteps(N)
|
||||
Next N
|
||||
ShowCount(2000) '4.
|
||||
ShowCount(20000) '4a.
|
||||
Sleep
|
||||
94
Task/Minimal-steps-down-to-1/Go/minimal-steps-down-to-1.go
Normal file
94
Task/Minimal-steps-down-to-1/Go/minimal-steps-down-to-1.go
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const limit = 50000
|
||||
|
||||
var (
|
||||
divs, subs []int
|
||||
mins [][]string
|
||||
)
|
||||
|
||||
// Assumes the numbers are presented in order up to 'limit'.
|
||||
func minsteps(n int) {
|
||||
if n == 1 {
|
||||
mins[1] = []string{}
|
||||
return
|
||||
}
|
||||
min := limit
|
||||
var p, q int
|
||||
var op byte
|
||||
for _, div := range divs {
|
||||
if n%div == 0 {
|
||||
d := n / div
|
||||
steps := len(mins[d]) + 1
|
||||
if steps < min {
|
||||
min = steps
|
||||
p, q, op = d, div, '/'
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, sub := range subs {
|
||||
if d := n - sub; d >= 1 {
|
||||
steps := len(mins[d]) + 1
|
||||
if steps < min {
|
||||
min = steps
|
||||
p, q, op = d, sub, '-'
|
||||
}
|
||||
}
|
||||
}
|
||||
mins[n] = append(mins[n], fmt.Sprintf("%c%d -> %d", op, q, p))
|
||||
mins[n] = append(mins[n], mins[p]...)
|
||||
}
|
||||
|
||||
func main() {
|
||||
for r := 0; r < 2; r++ {
|
||||
divs = []int{2, 3}
|
||||
if r == 0 {
|
||||
subs = []int{1}
|
||||
} else {
|
||||
subs = []int{2}
|
||||
}
|
||||
mins = make([][]string, limit+1)
|
||||
fmt.Printf("With: Divisors: %v, Subtractors: %v =>\n", divs, subs)
|
||||
fmt.Println(" Minimum number of steps to diminish the following numbers down to 1 is:")
|
||||
for i := 1; i <= limit; i++ {
|
||||
minsteps(i)
|
||||
if i <= 10 {
|
||||
steps := len(mins[i])
|
||||
plural := "s"
|
||||
if steps == 1 {
|
||||
plural = " "
|
||||
}
|
||||
fmt.Printf(" %2d: %d step%s: %s\n", i, steps, plural, strings.Join(mins[i], ", "))
|
||||
}
|
||||
}
|
||||
for _, lim := range []int{2000, 20000, 50000} {
|
||||
max := 0
|
||||
for _, min := range mins[0 : lim+1] {
|
||||
m := len(min)
|
||||
if m > max {
|
||||
max = m
|
||||
}
|
||||
}
|
||||
var maxs []int
|
||||
for i, min := range mins[0 : lim+1] {
|
||||
if len(min) == max {
|
||||
maxs = append(maxs, i)
|
||||
}
|
||||
}
|
||||
nums := len(maxs)
|
||||
verb, verb2, plural := "are", "have", "s"
|
||||
if nums == 1 {
|
||||
verb, verb2, plural = "is", "has", ""
|
||||
}
|
||||
fmt.Printf(" There %s %d number%s in the range 1-%d ", verb, nums, plural, lim)
|
||||
fmt.Printf("that %s maximum 'minimal steps' of %d:\n", verb2, max)
|
||||
fmt.Println(" ", maxs)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
{-# LANGUAGE DeriveFunctor #-}
|
||||
import Data.List
|
||||
import Data.Ord
|
||||
import Data.Function (on)
|
||||
|
||||
------------------------------------------------------------
|
||||
-- memoization utilities
|
||||
|
||||
data Memo a = Node a (Memo a) (Memo a)
|
||||
deriving Functor
|
||||
|
||||
memo :: Integral a => Memo p -> a -> p
|
||||
memo (Node a l r) n
|
||||
| n == 0 = a
|
||||
| odd n = memo l (n `div` 2)
|
||||
| otherwise = memo r (n `div` 2 - 1)
|
||||
|
||||
nats :: Integral a => Memo a
|
||||
nats = Node 0 ((+1).(*2) <$> nats) ((*2).(+1) <$> nats)
|
||||
|
||||
memoize :: Integral a => (a -> b) -> (a -> b)
|
||||
memoize f = memo (f <$> nats)
|
||||
|
||||
------------------------------------------------------------
|
||||
|
||||
data Step = Div Int | Sub Int
|
||||
deriving Show
|
||||
|
||||
run :: Int -> Step -> [(Step, Int)]
|
||||
run n s = case s of
|
||||
Sub i | n > i -> [(s, n - i)]
|
||||
Div d | n `mod` d == 0 -> [(s, n `div` d)]
|
||||
_ -> []
|
||||
|
||||
minSteps :: [Step] -> Int -> (Int, [Step])
|
||||
minSteps steps = go
|
||||
where
|
||||
go = memoize goM
|
||||
|
||||
goM 1 = (0, [])
|
||||
goM n = minimumBy (comparing fst) $ do
|
||||
(s, k) <- steps >>= run n
|
||||
let (m, ss) = go k
|
||||
return (m+1, s:ss)
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
showSteps :: Int -> [Step] -> String
|
||||
showSteps = foldl go . show
|
||||
where
|
||||
go r (Div d) = r ++ "/" ++ show d
|
||||
go r (Sub s) = "(" ++ r ++ "-" ++ show s ++ ")"
|
||||
|
||||
|
||||
task steps = mapM_ (put . go) [1..10]
|
||||
where
|
||||
go n = showSteps n <$> minSteps steps n
|
||||
put (n,s) = putStrLn $ show n ++ ":\t" ++ s
|
||||
|
||||
task2 steps range = mapM_ put longest
|
||||
where
|
||||
put (n,(l,s)) = putStrLn $ show l ++ ": " ++
|
||||
showSteps n s
|
||||
longest =
|
||||
head $ groupBy ((==) `on` (fst.snd)) $
|
||||
sortOn (negate . fst . snd) $
|
||||
zip [1..] (minSteps steps <$> range)
|
||||
20
Task/Minimal-steps-down-to-1/J/minimal-steps-down-to-1-1.j
Normal file
20
Task/Minimal-steps-down-to-1/J/minimal-steps-down-to-1-1.j
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
step=: {{
|
||||
~.((#~ 1<:]),y-/m),(#~ (=<.)),y%/n
|
||||
}}
|
||||
|
||||
steps=: {{
|
||||
m step n^:(1 - 1 e. ])^:a:
|
||||
}}
|
||||
|
||||
show=: {{
|
||||
paths=.,:,:0 0 1 NB. operator, operand, net value
|
||||
m=.,m [ n=.,n NB. m: subtractors, n: divisors
|
||||
for_ok.}.|.m steps n y do. NB. ok: valid net values
|
||||
last=.{."2 paths
|
||||
subs=. (1,.m,.0)+"2]0 0 1*"1 last+"1 0/m
|
||||
divs=. (2,.n,.0)+"2]0 0 1*"1 last*"1 0/n
|
||||
prev=. subs,"2 divs NB. we are working backwards from 1
|
||||
paths=. (,({:"1 prev)e.ok)#,/prev,"1 2/"2 paths
|
||||
end.
|
||||
;@((<":y),,)"2((' -/'{~{.);":@{:)"1}:"2}:"1 paths
|
||||
}}
|
||||
113
Task/Minimal-steps-down-to-1/J/minimal-steps-down-to-1-2.j
Normal file
113
Task/Minimal-steps-down-to-1/J/minimal-steps-down-to-1-2.j
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
taskA=: {{
|
||||
for_j. 1+i.10 do.
|
||||
echo rplc&(' 1 steps';' 1 step')j,&":': ',(_1+#x steps y j),&":' steps.'
|
||||
echo x show y j
|
||||
echo ''
|
||||
end.
|
||||
}}
|
||||
|
||||
taskB=: {{
|
||||
echo 'considering positive integers up to ',":m
|
||||
tallies=. _1+#@(x steps y)every 1+i.m
|
||||
echo (>./tallies) ,&": ' steps: ',&": 1+I.(=>./)tallies
|
||||
echo ''
|
||||
}}
|
||||
|
||||
task=: 2e4 taskB, 2e3 taskB, taskA
|
||||
|
||||
1 task 2 3
|
||||
1: 0 steps.
|
||||
1
|
||||
|
||||
2: 1 step.
|
||||
2-1
|
||||
2/2
|
||||
|
||||
3: 1 step.
|
||||
3/3
|
||||
|
||||
4: 2 steps.
|
||||
4/2-1
|
||||
4/2/2
|
||||
4-1/3
|
||||
|
||||
5: 3 steps.
|
||||
5-1/2-1
|
||||
5-1/2/2
|
||||
5-1-1/3
|
||||
|
||||
6: 2 steps.
|
||||
6/3-1
|
||||
6/3/2
|
||||
6/2/3
|
||||
|
||||
7: 3 steps.
|
||||
7-1/3-1
|
||||
7-1/3/2
|
||||
7-1/2/3
|
||||
|
||||
8: 3 steps.
|
||||
8/2/2-1
|
||||
8/2/2/2
|
||||
8/2-1/3
|
||||
|
||||
9: 2 steps.
|
||||
9/3/3
|
||||
|
||||
10: 3 steps.
|
||||
10-1/3/3
|
||||
|
||||
considering positive integers up to 2000
|
||||
14 steps: 863 1079 1295 1439 1511 1583 1607 1619 1691 1727 1823 1871 1895 1907 1919 1943
|
||||
|
||||
considering positive integers up to 20000
|
||||
20 steps: 12959 15551 17279 18143 19439
|
||||
|
||||
2 task 2 3
|
||||
1: 0 steps.
|
||||
1
|
||||
|
||||
2: 1 step.
|
||||
2/2
|
||||
|
||||
3: 1 step.
|
||||
3-2
|
||||
3/3
|
||||
|
||||
4: 2 steps.
|
||||
4-2/2
|
||||
4/2/2
|
||||
|
||||
5: 2 steps.
|
||||
5-2-2
|
||||
5-2/3
|
||||
|
||||
6: 2 steps.
|
||||
6/2-2
|
||||
6/3/2
|
||||
6/2/3
|
||||
|
||||
7: 3 steps.
|
||||
7-2-2-2
|
||||
7-2-2/3
|
||||
|
||||
8: 3 steps.
|
||||
8-2/2-2
|
||||
8/2-2/2
|
||||
8/2/2/2
|
||||
8-2/3/2
|
||||
8-2/2/3
|
||||
|
||||
9: 2 steps.
|
||||
9/3-2
|
||||
9/3/3
|
||||
|
||||
10: 3 steps.
|
||||
10/2-2-2
|
||||
10/2-2/3
|
||||
|
||||
considering positive integers up to 2000
|
||||
17 steps: 1699
|
||||
|
||||
considering positive integers up to 20000
|
||||
24 steps: 19681
|
||||
214
Task/Minimal-steps-down-to-1/Java/minimal-steps-down-to-1.java
Normal file
214
Task/Minimal-steps-down-to-1/Java/minimal-steps-down-to-1.java
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class MinimalStepsDownToOne {
|
||||
|
||||
public static void main(String[] args) {
|
||||
runTasks(getFunctions1());
|
||||
runTasks(getFunctions2());
|
||||
runTasks(getFunctions3());
|
||||
}
|
||||
|
||||
private static void runTasks(List<Function> functions) {
|
||||
Map<Integer,List<String>> minPath = getInitialMap(functions, 5);
|
||||
|
||||
// Task 1
|
||||
int max = 10;
|
||||
populateMap(minPath, functions, max);
|
||||
System.out.printf("%nWith functions: %s%n", functions);
|
||||
System.out.printf(" Minimum steps to 1:%n");
|
||||
for ( int n = 2 ; n <= max ; n++ ) {
|
||||
int steps = minPath.get(n).size();
|
||||
System.out.printf(" %2d: %d step%1s: %s%n", n, steps, steps == 1 ? "" : "s", minPath.get(n));
|
||||
}
|
||||
|
||||
// Task 2
|
||||
displayMaxMin(minPath, functions, 2000);
|
||||
|
||||
// Task 2a
|
||||
displayMaxMin(minPath, functions, 20000);
|
||||
|
||||
// Task 2a +
|
||||
displayMaxMin(minPath, functions, 100000);
|
||||
}
|
||||
|
||||
private static void displayMaxMin(Map<Integer,List<String>> minPath, List<Function> functions, int max) {
|
||||
populateMap(minPath, functions, max);
|
||||
List<Integer> maxIntegers = getMaxMin(minPath, max);
|
||||
int maxSteps = maxIntegers.remove(0);
|
||||
int numCount = maxIntegers.size();
|
||||
System.out.printf(" There %s %d number%s in the range 1-%d that have maximum 'minimal steps' of %d:%n %s%n", numCount == 1 ? "is" : "are", numCount, numCount == 1 ? "" : "s", max, maxSteps, maxIntegers);
|
||||
|
||||
}
|
||||
|
||||
private static List<Integer> getMaxMin(Map<Integer,List<String>> minPath, int max) {
|
||||
int maxSteps = Integer.MIN_VALUE;
|
||||
List<Integer> maxIntegers = new ArrayList<Integer>();
|
||||
for ( int n = 2 ; n <= max ; n++ ) {
|
||||
int len = minPath.get(n).size();
|
||||
if ( len > maxSteps ) {
|
||||
maxSteps = len;
|
||||
maxIntegers.clear();
|
||||
maxIntegers.add(n);
|
||||
}
|
||||
else if ( len == maxSteps ) {
|
||||
maxIntegers.add(n);
|
||||
}
|
||||
}
|
||||
maxIntegers.add(0, maxSteps);
|
||||
return maxIntegers;
|
||||
}
|
||||
|
||||
private static void populateMap(Map<Integer,List<String>> minPath, List<Function> functions, int max) {
|
||||
for ( int n = 2 ; n <= max ; n++ ) {
|
||||
if ( minPath.containsKey(n) ) {
|
||||
continue;
|
||||
}
|
||||
Function minFunction = null;
|
||||
int minSteps = Integer.MAX_VALUE;
|
||||
for ( Function f : functions ) {
|
||||
if ( f.actionOk(n) ) {
|
||||
int result = f.action(n);
|
||||
int steps = 1 + minPath.get(result).size();
|
||||
if ( steps < minSteps ) {
|
||||
minFunction = f;
|
||||
minSteps = steps;
|
||||
}
|
||||
}
|
||||
}
|
||||
int result = minFunction.action(n);
|
||||
List<String> path = new ArrayList<String>();
|
||||
path.add(minFunction.toString(n));
|
||||
path.addAll(minPath.get(result));
|
||||
minPath.put(n, path);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Map<Integer,List<String>> getInitialMap(List<Function> functions, int max) {
|
||||
Map<Integer,List<String>> minPath = new HashMap<>();
|
||||
for ( int i = 2 ; i <= max ; i++ ) {
|
||||
for ( Function f : functions ) {
|
||||
if ( f.actionOk(i) ) {
|
||||
int result = f.action(i);
|
||||
if ( result == 1 ) {
|
||||
List<String> path = new ArrayList<String>();
|
||||
path.add(f.toString(i));
|
||||
minPath.put(i, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return minPath;
|
||||
}
|
||||
|
||||
private static List<Function> getFunctions3() {
|
||||
List<Function> functions = new ArrayList<>();
|
||||
functions.add(new Divide2Function());
|
||||
functions.add(new Divide3Function());
|
||||
functions.add(new Subtract2Function());
|
||||
functions.add(new Subtract1Function());
|
||||
return functions;
|
||||
}
|
||||
|
||||
private static List<Function> getFunctions2() {
|
||||
List<Function> functions = new ArrayList<>();
|
||||
functions.add(new Divide3Function());
|
||||
functions.add(new Divide2Function());
|
||||
functions.add(new Subtract2Function());
|
||||
return functions;
|
||||
}
|
||||
|
||||
private static List<Function> getFunctions1() {
|
||||
List<Function> functions = new ArrayList<>();
|
||||
functions.add(new Divide3Function());
|
||||
functions.add(new Divide2Function());
|
||||
functions.add(new Subtract1Function());
|
||||
return functions;
|
||||
}
|
||||
|
||||
public abstract static class Function {
|
||||
abstract public int action(int n);
|
||||
abstract public boolean actionOk(int n);
|
||||
abstract public String toString(int n);
|
||||
}
|
||||
|
||||
public static class Divide2Function extends Function {
|
||||
@Override public int action(int n) {
|
||||
return n/2;
|
||||
}
|
||||
|
||||
@Override public boolean actionOk(int n) {
|
||||
return n % 2 == 0;
|
||||
}
|
||||
|
||||
@Override public String toString(int n) {
|
||||
return "/2 -> " + n/2;
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return "Divisor 2";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Divide3Function extends Function {
|
||||
@Override public int action(int n) {
|
||||
return n/3;
|
||||
}
|
||||
|
||||
@Override public boolean actionOk(int n) {
|
||||
return n % 3 == 0;
|
||||
}
|
||||
|
||||
@Override public String toString(int n) {
|
||||
return "/3 -> " + n/3;
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return "Divisor 3";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Subtract1Function extends Function {
|
||||
@Override public int action(int n) {
|
||||
return n-1;
|
||||
}
|
||||
|
||||
@Override public boolean actionOk(int n) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override public String toString(int n) {
|
||||
return "-1 -> " + (n-1);
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return "Subtractor 1";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Subtract2Function extends Function {
|
||||
@Override public int action(int n) {
|
||||
return n-2;
|
||||
}
|
||||
|
||||
@Override public boolean actionOk(int n) {
|
||||
return n > 2;
|
||||
}
|
||||
|
||||
@Override public String toString(int n) {
|
||||
return "-2 -> " + (n-2);
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return "Subtractor 2";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
import Base.print
|
||||
|
||||
struct Action{T}
|
||||
f::Function
|
||||
i::T
|
||||
end
|
||||
|
||||
struct ActionOutcome{T}
|
||||
act::Action{T}
|
||||
out::T
|
||||
end
|
||||
|
||||
Base.print(io::IO, ao::ActionOutcome) = print(io, "$(ao.act.f) $(ao.act.i) yields $(ao.out)")
|
||||
|
||||
memoized = Dict{Int, Int}()
|
||||
|
||||
function findshortest(start, goal, fails, actions, verbose=true, maxsteps=100000)
|
||||
solutions, numsteps = Vector{Vector{ActionOutcome}}(), 0
|
||||
seqs = [ActionOutcome[ActionOutcome(Action(div, 0), start)]]
|
||||
if start == goal
|
||||
verbose && println("For start of $start, no steps needed.\n")
|
||||
return 0
|
||||
end
|
||||
while numsteps < maxsteps && isempty(solutions)
|
||||
newsequences = Vector{Vector{ActionOutcome}}()
|
||||
numsteps += 1
|
||||
for seq in seqs
|
||||
for (act, arr) in actions, x in arr
|
||||
result = act(seq[end].out, x)
|
||||
if !fails(result)
|
||||
newactionseq = vcat(seq, ActionOutcome(Action(act, x), result))
|
||||
numsteps == 1 && popfirst!(newactionseq)
|
||||
if result == goal
|
||||
push!(solutions, newactionseq)
|
||||
else
|
||||
push!(newsequences, newactionseq)
|
||||
end
|
||||
end
|
||||
end
|
||||
if !verbose && isempty(solutions) &&
|
||||
all(x -> haskey(memoized, x[end].out), newsequences)
|
||||
minresult = minimum(x -> memoized[x[end].out], newsequences) + numsteps
|
||||
memoized[start] = minresult
|
||||
return minresult
|
||||
end
|
||||
end
|
||||
seqs = newsequences
|
||||
end
|
||||
if verbose
|
||||
l = length(solutions)
|
||||
print("There ", l > 1 ? "are $l solutions" : "is $l solution",
|
||||
" for path of length ", numsteps, " from $start to $goal.\nExample: ")
|
||||
for step in solutions[1]
|
||||
print(step, step.out == 1 ? "\n\n" : ", ")
|
||||
end
|
||||
end
|
||||
memoized[start] = numsteps
|
||||
return numsteps
|
||||
end
|
||||
|
||||
failed(n) = n < 1
|
||||
|
||||
const divisors = [2, 3]
|
||||
divide(n, x) = begin q, r = divrem(n, x); r == 0 ? q : -1 end
|
||||
|
||||
const subtractors1, subtractors2 = [1], [2]
|
||||
subtract(n, x) = n - x
|
||||
|
||||
actions1 = Dict(divide => divisors, subtract => subtractors1)
|
||||
actions2 = Dict(divide => divisors, subtract => subtractors2)
|
||||
|
||||
function findmaxshortest(g, fails, acts, maxn)
|
||||
stepcounts = [findshortest(n, g, fails, acts, false) for n in 1:maxn]
|
||||
maxs = maximum(stepcounts)
|
||||
maxstepnums = findall(x -> x == maxs, stepcounts)
|
||||
println("There are $(length(maxstepnums)) with $maxs steps for start between 1 and $maxn: ", maxstepnums)
|
||||
end
|
||||
|
||||
function teststeps(g, fails, acts, maxes)
|
||||
println("\nWith goal $g, divisors $(acts[divide]), subtractors $(acts[subtract]):")
|
||||
for n in 1:10
|
||||
findshortest(n, g, fails, acts)
|
||||
end
|
||||
for maxn in maxes
|
||||
findmaxshortest(g, fails, acts, maxn)
|
||||
end
|
||||
end
|
||||
|
||||
teststeps(1, failed, actions1, [2000, 20000, 50000])
|
||||
empty!(memoized)
|
||||
teststeps(1, failed, actions2, [2000, 20000, 50000])
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
$RecursionLimit = 3000;
|
||||
ClearAll[MinimalStepToOne, MinimalStepToOneHelper]
|
||||
MinimalStepToOne[n_Integer] := Module[{res},
|
||||
res = Reap[MinimalStepToOneHelper[{n}]][[-1, 1]];
|
||||
SortBy[res, Length]
|
||||
]
|
||||
MinimalStepToOneHelper[steps_List] := Module[{n, out},
|
||||
n = Last[steps];
|
||||
If[n == 1,
|
||||
Sow[steps];
|
||||
,
|
||||
If[Divisible[n, 3],
|
||||
out = steps~Join~{" /3=> ", n/3};
|
||||
MinimalStepToOneHelper[out]
|
||||
];
|
||||
If[Divisible[n, 2],
|
||||
out = steps~Join~{" /2=> ", n/2};
|
||||
MinimalStepToOneHelper[out]
|
||||
];
|
||||
If[n > 1,
|
||||
out = steps~Join~{" -1=> ", n - 1};
|
||||
MinimalStepToOneHelper[out]
|
||||
];
|
||||
]
|
||||
]
|
||||
Do[
|
||||
sel = First[MinimalStepToOne[i]];
|
||||
Print[First[sel],
|
||||
": (" <> ToString[(Length[sel] - 1)/2] <> " steps) ", sel // Row]
|
||||
,
|
||||
{i, 1, 10}
|
||||
]
|
||||
|
||||
$RecursionLimit = 3000;
|
||||
ClearAll[MinimalStepToOne2, MinimalStepToOneHelper2]
|
||||
MinimalStepToOne2[nn_Integer] :=
|
||||
Module[{res, done, solution, maxsteps},
|
||||
done = False;
|
||||
solution = {};
|
||||
MinimalStepToOneHelper2[steps_List] := Module[{n, out},
|
||||
n = Last[steps];
|
||||
If[n == 1,
|
||||
solution = steps;
|
||||
,
|
||||
If[solution === {},
|
||||
If[Divisible[n, 3],
|
||||
out = steps~Join~{" /3=> ", n/3};
|
||||
MinimalStepToOneHelper2[out]
|
||||
];
|
||||
If[Divisible[n, 2],
|
||||
out = steps~Join~{" /2=> ", n/2};
|
||||
MinimalStepToOneHelper2[out]
|
||||
];
|
||||
If[n > 1,
|
||||
out = steps~Join~{" -1=> ", n - 1};
|
||||
MinimalStepToOneHelper2[out]
|
||||
];
|
||||
];
|
||||
];
|
||||
];
|
||||
MinimalStepToOneHelper2[{nn}];
|
||||
maxsteps = (Length[solution] - 1)/2;
|
||||
maxsteps
|
||||
]
|
||||
|
||||
$RecursionLimit = 3000;
|
||||
ClearAll[MinimalStepToOneMaxSteps, MinimalStepToOneMaxStepsHelper]
|
||||
MinimalStepToOneMaxSteps[n_Integer, maxsteps_Integer] :=
|
||||
Module[{res},
|
||||
res = Reap[MinimalStepToOneMaxStepsHelper[{n}, maxsteps]][[-1, 1]];
|
||||
(Min[Length /@ res] - 1)/2
|
||||
]
|
||||
MinimalStepToOneMaxStepsHelper[steps_List, maxsteps_Integer] :=
|
||||
Module[{n, out},
|
||||
n = Last[steps];
|
||||
If[n == 1,
|
||||
Sow[steps];
|
||||
,
|
||||
If[maxsteps > 0,
|
||||
If[Divisible[n, 3],
|
||||
out = steps~Join~{" /3=> ", n/3};
|
||||
MinimalStepToOneMaxStepsHelper[out, maxsteps - 1]
|
||||
];
|
||||
If[Divisible[n, 2],
|
||||
out = steps~Join~{" /2=> ", n/2};
|
||||
MinimalStepToOneMaxStepsHelper[out, maxsteps - 1]
|
||||
];
|
||||
If[n > 1,
|
||||
out = steps~Join~{" -1=> ", n - 1};
|
||||
MinimalStepToOneMaxStepsHelper[out, maxsteps - 1]
|
||||
];
|
||||
];
|
||||
];
|
||||
]
|
||||
|
||||
allsols = Table[
|
||||
max = MinimalStepToOne2[i];
|
||||
{i, MinimalStepToOneMaxSteps[i, max]}
|
||||
,
|
||||
{i, 1, 2000}
|
||||
];
|
||||
|
||||
a = Last[SortBy[GatherBy[allsols, Last], First /* Last]];
|
||||
{a[[1, 2]], a[[All, 1]]}
|
||||
|
||||
$RecursionLimit = 3000;
|
||||
ClearAll[MinimalStepToOne, MinimalStepToOneHelper]
|
||||
MinimalStepToOne[n_Integer] := Module[{res},
|
||||
res = Reap[MinimalStepToOneHelper[{n}]][[-1, 1]];
|
||||
SortBy[res, Length]
|
||||
]
|
||||
MinimalStepToOneHelper[steps_List] := Module[{n, out},
|
||||
n = Last[steps];
|
||||
If[n == 1,
|
||||
Sow[steps];
|
||||
,
|
||||
If[Divisible[n, 3],
|
||||
out = steps~Join~{" /3=> ", n/3};
|
||||
MinimalStepToOneHelper[out]
|
||||
];
|
||||
If[Divisible[n, 2],
|
||||
out = steps~Join~{" /2=> ", n/2};
|
||||
MinimalStepToOneHelper[out]
|
||||
];
|
||||
If[n > 2,
|
||||
out = steps~Join~{" -2=> ", n - 2};
|
||||
MinimalStepToOneHelper[out]
|
||||
];
|
||||
]
|
||||
]
|
||||
Do[
|
||||
sel = First[MinimalStepToOne[i]];
|
||||
Print[First[sel],
|
||||
": (" <> ToString[(Length[sel] - 1)/2] <> " steps) ", sel // Row]
|
||||
,
|
||||
{i, 1, 10}
|
||||
]
|
||||
|
||||
$RecursionLimit = 3000;
|
||||
ClearAll[MinimalStepToOne2, MinimalStepToOneHelper2]
|
||||
MinimalStepToOne2[nn_Integer] :=
|
||||
Module[{res, done, solution, maxsteps},
|
||||
done = False;
|
||||
solution = {};
|
||||
MinimalStepToOneHelper2[steps_List] := Module[{n, out},
|
||||
n = Last[steps];
|
||||
If[n == 1,
|
||||
solution = steps;
|
||||
,
|
||||
If[solution === {},
|
||||
If[Divisible[n, 3],
|
||||
out = steps~Join~{" /3=> ", n/3};
|
||||
MinimalStepToOneHelper2[out]
|
||||
];
|
||||
If[Divisible[n, 2],
|
||||
out = steps~Join~{" /2=> ", n/2};
|
||||
MinimalStepToOneHelper2[out]
|
||||
];
|
||||
If[n > 2,
|
||||
out = steps~Join~{" -2=> ", n - 2};
|
||||
MinimalStepToOneHelper2[out]
|
||||
];
|
||||
];
|
||||
];
|
||||
];
|
||||
MinimalStepToOneHelper2[{nn}];
|
||||
maxsteps = (Length[solution] - 1)/2;
|
||||
maxsteps
|
||||
]
|
||||
|
||||
$RecursionLimit = 3000;
|
||||
ClearAll[MinimalStepToOneMaxSteps, MinimalStepToOneMaxStepsHelper]
|
||||
MinimalStepToOneMaxSteps[n_Integer, maxsteps_Integer] :=
|
||||
Module[{res},
|
||||
res = Reap[MinimalStepToOneMaxStepsHelper[{n}, maxsteps]][[-1, 1]];
|
||||
(Min[Length /@ res] - 1)/2
|
||||
]
|
||||
MinimalStepToOneMaxStepsHelper[steps_List, maxsteps_Integer] :=
|
||||
Module[{n, out},
|
||||
n = Last[steps];
|
||||
If[n == 1,
|
||||
Sow[steps];
|
||||
,
|
||||
If[maxsteps > 0,
|
||||
If[Divisible[n, 3],
|
||||
out = steps~Join~{" /3=> ", n/3};
|
||||
MinimalStepToOneMaxStepsHelper[out, maxsteps - 1]
|
||||
];
|
||||
If[Divisible[n, 2],
|
||||
out = steps~Join~{" /2=> ", n/2};
|
||||
MinimalStepToOneMaxStepsHelper[out, maxsteps - 1]
|
||||
];
|
||||
If[n > 2,
|
||||
out = steps~Join~{" -2=> ", n - 2};
|
||||
MinimalStepToOneMaxStepsHelper[out, maxsteps - 1]
|
||||
];
|
||||
];
|
||||
];
|
||||
]
|
||||
|
||||
allsols = Table[
|
||||
max = MinimalStepToOne2[i];
|
||||
{i, MinimalStepToOneMaxSteps[i, max]}
|
||||
,
|
||||
{i, 1, 2000}
|
||||
];
|
||||
|
||||
a = Last[SortBy[GatherBy[allsols, Last], First /* Last]];
|
||||
{a[[1, 2]], a[[All, 1]]}
|
||||
121
Task/Minimal-steps-down-to-1/Nim/minimal-steps-down-to-1.nim
Normal file
121
Task/Minimal-steps-down-to-1/Nim/minimal-steps-down-to-1.nim
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
import strformat, strutils, tables
|
||||
|
||||
type
|
||||
|
||||
Sequence = seq[Natural]
|
||||
|
||||
Context = object
|
||||
divisors: seq[int]
|
||||
subtractors: seq[int]
|
||||
seqCache: Table[int, Sequence] # Mapping number -> sequence to reach 1.
|
||||
stepCache: Table[int, int] # Mapping number -> number of steps to reach 1.
|
||||
|
||||
|
||||
proc initContext(divisors, subtractors: openArray[int]): Context =
|
||||
## Initialize a context.
|
||||
for d in divisors: doAssert d > 1, "divisors must be greater than 1."
|
||||
for s in subtractors: doAssert s > 0, "substractors must be greater than 0."
|
||||
result.divisors = @divisors
|
||||
result.subtractors = @subtractors
|
||||
result.seqCache[1] = @[Natural 1]
|
||||
result.stepCache[1] = 0
|
||||
|
||||
|
||||
proc minStepsDown(context: var Context; n: Natural): Sequence =
|
||||
# Return a minimal sequence to reach the value 1.
|
||||
|
||||
assert n > 0, "“n” must be positive."
|
||||
if n in context.seqCache: return context.seqCache[n]
|
||||
|
||||
var
|
||||
minSteps = int.high
|
||||
minPath: Sequence
|
||||
|
||||
for val in context.divisors:
|
||||
if n mod val == 0:
|
||||
var path = context.minStepsDown(n div val)
|
||||
if path.len < minSteps:
|
||||
minSteps = path.len
|
||||
minPath = move(path)
|
||||
|
||||
for val in context.subtractors:
|
||||
if n - val > 0:
|
||||
var path = context.minStepsDown(n - val)
|
||||
if path.len < minSteps:
|
||||
minSteps = path.len
|
||||
minPath = move(path)
|
||||
|
||||
result = n & minPath
|
||||
context.seqCache[n] = result
|
||||
|
||||
|
||||
proc minStepsDownCount(context: var Context; n: Natural): int =
|
||||
## Compute the mininum number of steps without keeping the sequence.
|
||||
|
||||
assert n > 0, "“n” must be positive."
|
||||
if n in context.stepCache: return context.stepCache[n]
|
||||
|
||||
result = int.high
|
||||
|
||||
for val in context.divisors:
|
||||
if n mod val == 0:
|
||||
let steps = context.minStepsDownCount(n div val)
|
||||
if steps < result: result = steps
|
||||
|
||||
for val in context.subtractors:
|
||||
if n - val > 0:
|
||||
let steps = context.minStepsDownCount(n - val)
|
||||
if steps < result: result = steps
|
||||
|
||||
inc result
|
||||
context.stepCache[n] = result
|
||||
|
||||
|
||||
template plural(n: int): string =
|
||||
if n > 1: "s" else: ""
|
||||
|
||||
proc printMinStepsDown(context: var Context; n: Natural) =
|
||||
## Search and print the sequence to reach one.
|
||||
|
||||
let sol = context.minStepsDown(n)
|
||||
stdout.write &"{n} takes {sol.len - 1} step{plural(sol.len - 1)}: "
|
||||
var prev = 0
|
||||
for val in sol:
|
||||
if prev == 0:
|
||||
stdout.write val
|
||||
elif prev - val in context.subtractors:
|
||||
stdout.write " - ", prev - val, " → ", val
|
||||
else:
|
||||
stdout.write " / ", prev div val, " → ", val
|
||||
prev = val
|
||||
stdout.write '\n'
|
||||
|
||||
|
||||
proc maxMinStepsCount(context: var Context; nmax: Positive): tuple[steps: int; list: seq[int]] =
|
||||
## Return the maximal number of steps needed for numbers between 1 and "nmax"
|
||||
## and the list of numbers needing this number of steps.
|
||||
|
||||
for n in 2..nmax:
|
||||
let nsteps = context.minStepsDownCount(n)
|
||||
if nsteps == result.steps:
|
||||
result.list.add n
|
||||
elif nsteps > result.steps:
|
||||
result.steps = nsteps
|
||||
result.list = @[n]
|
||||
|
||||
|
||||
proc run(divisors, subtractors: openArray[int]) =
|
||||
## Run the search for given divisors and subtractors.
|
||||
|
||||
var context = initContext(divisors, subtractors)
|
||||
echo &"Using divisors: {divisors} and substractors: {subtractors}"
|
||||
for n in 1..10: context.printMinStepsDown(n)
|
||||
for nmax in [2_000, 20_000]:
|
||||
let (steps, list) = context.maxMinStepsCount(nmax)
|
||||
stdout.write if list.len == 1: &"There is 1 number " else: &"There are {list.len} numbers "
|
||||
echo &"below {nmax} that require {steps} steps: ", list.join(", ")
|
||||
|
||||
|
||||
run(divisors = [2, 3], subtractors = [1])
|
||||
echo ""
|
||||
run(divisors = [2, 3], subtractors = [2])
|
||||
48
Task/Minimal-steps-down-to-1/Perl/minimal-steps-down-to-1.pl
Normal file
48
Task/Minimal-steps-down-to-1/Perl/minimal-steps-down-to-1.pl
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict; # https://rosettacode.org/wiki/Minimal_steps_down_to_1
|
||||
use warnings;
|
||||
no warnings 'recursion';
|
||||
use List::Util qw( first );
|
||||
use Data::Dump 'dd';
|
||||
|
||||
for ( [ 2000, [2, 3], [1] ], [ 2000, [2, 3], [2] ] )
|
||||
{
|
||||
my ( $n, $div, $sub ) = @$_;
|
||||
print "\n", '-' x 40, " divisors @$div subtractors @$sub\n";
|
||||
my ($solve, $max) = minimal( @$_ );
|
||||
printf "%4d takes %s step(s): %s\n",
|
||||
$_, $solve->[$_] =~ tr/ // - 1, $solve->[$_] for 1 .. 10;
|
||||
print "\n";
|
||||
printf "%d number(s) below %d that take $#$max steps: %s\n",
|
||||
$max->[-1] =~ tr/ //, $n, $max->[-1];
|
||||
($solve, $max) = minimal( 20000, $div, $sub );
|
||||
printf "%d number(s) below %d that take $#$max steps: %s\n",
|
||||
$max->[-1] =~ tr/ //, 20000, $max->[-1];
|
||||
}
|
||||
|
||||
sub minimal
|
||||
{
|
||||
my ($top, $div, $sub) = @_;
|
||||
my @solve = (0, ' ');
|
||||
my @maximal;
|
||||
for my $n ( 2 .. $top )
|
||||
{
|
||||
my @pick;
|
||||
for my $d ( @$div )
|
||||
{
|
||||
$n % $d and next;
|
||||
my $ans = "/$d $solve[$n / $d]";
|
||||
$pick[$ans =~ tr/ //] //= $ans;
|
||||
}
|
||||
for my $s ( @$sub )
|
||||
{
|
||||
$n > $s or next;
|
||||
my $ans = "-$s $solve[$n - $s]";
|
||||
$pick[$ans =~ tr/ //] //= $ans;
|
||||
}
|
||||
$solve[$n] = first { defined } @pick;
|
||||
$maximal[$solve[$n] =~ tr/ // - 1] .= " $n";
|
||||
}
|
||||
return \@solve, \@maximal;
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">cache</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span>
|
||||
<span style="color: #000000;">ckeys</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
|
||||
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">ms21</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">ds</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">cdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">find</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ds</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ckeys</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">cdx</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">ckeys</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ckeys</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ds</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">cache</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cache</span><span style="color: #0000FF;">,{{}})</span>
|
||||
<span style="color: #000000;">cdx</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cache</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cache</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cdx</span><span style="color: #0000FF;">])+</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">ms</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">steps</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ds</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span> <span style="color: #000080;font-style:italic;">-- (d then s)</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ds</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">dsk</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ds</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">][</span><span style="color: #000000;">k</span><span style="color: #0000FF;">],</span>
|
||||
<span style="color: #000000;">ok</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">?</span><span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dsk</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">:</span><span style="color: #000000;">i</span><span style="color: #0000FF;">></span><span style="color: #000000;">dsk</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">ok</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">?</span><span style="color: #000000;">i</span><span style="color: #0000FF;">/</span><span style="color: #000000;">dsk</span><span style="color: #0000FF;">:</span><span style="color: #000000;">i</span><span style="color: #0000FF;">-</span><span style="color: #000000;">dsk</span><span style="color: #0000FF;">),</span>
|
||||
<span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cache</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cdx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">m</span><span style="color: #0000FF;">])+</span><span style="color: #000000;">1</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">ms</span><span style="color: #0000FF;">></span><span style="color: #000000;">l</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">ms</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">l</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">step</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%s%d -> %d"</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">"/-"</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">],</span><span style="color: #000000;">dsk</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #000000;">steps</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">prepend</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cache</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cdx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">m</span><span style="color: #0000FF;">]),</span><span style="color: #000000;">step</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">steps</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">cache</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cdx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cache</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cdx</span><span style="color: #0000FF;">],</span><span style="color: #000000;">steps</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">cache</span><span style="color: #0000FF;">[</span><span style="color: #000000;">cdx</span><span style="color: #0000FF;">][</span><span style="color: #000000;">n</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">show10</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">ds</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\nWith divisors %v and subtractors %v:\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ds</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">steps</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ms21</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ds</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">ns</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">steps</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #000000;">ps</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ns</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">?</span><span style="color: #008000;">""</span><span style="color: #0000FF;">:</span><span style="color: #008000;">"s"</span><span style="color: #0000FF;">),</span>
|
||||
<span style="color: #000000;">eg</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ns</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">?</span><span style="color: #008000;">""</span><span style="color: #0000FF;">:</span><span style="color: #008000;">", eg "</span><span style="color: #0000FF;">&</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">steps</span><span style="color: #0000FF;">,</span><span style="color: #008000;">","</span><span style="color: #0000FF;">))</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%2d takes %d step%s%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ns</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ps</span><span style="color: #0000FF;">,</span><span style="color: #000000;">eg</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
|
||||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">maxsteps</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">ds</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">lim</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">ms</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ls</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">mc</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{},</span> <span style="color: #000000;">steps</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">args</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">lim</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">steps</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ms21</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ds</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">ls</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">steps</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">ls</span><span style="color: #0000FF;">></span><span style="color: #000000;">ms</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">ms</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ls</span>
|
||||
<span style="color: #000000;">mc</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">}</span>
|
||||
<span style="color: #008080;">elsif</span> <span style="color: #000000;">ls</span><span style="color: #0000FF;">=</span><span style="color: #000000;">ms</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">mc</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">n</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">lm</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mc</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">string</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">are</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ps</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ns</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lm</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">?{</span><span style="color: #008000;">"is"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"s"</span><span style="color: #0000FF;">}:{</span><span style="color: #008000;">"are"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"s"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">})</span>
|
||||
<span style="color: #000000;">args</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span> <span style="color: #000000;">are</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lm</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ps</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">lim</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ns</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ms</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">shorten</span><span style="color: #0000FF;">(</span><span style="color: #000000;">mc</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)}</span>
|
||||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"There %s %d number%s below %d that require%s %d steps: %v\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">args</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
|
||||
|
||||
<span style="color: #000000;">show10</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}})</span>
|
||||
<span style="color: #000000;">maxsteps</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}},</span><span style="color: #000000;">2000</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">maxsteps</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}},</span><span style="color: #000000;">20000</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">maxsteps</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}},</span><span style="color: #000000;">50000</span><span style="color: #0000FF;">)</span>
|
||||
|
||||
<span style="color: #000000;">show10</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">}})</span>
|
||||
<span style="color: #000000;">maxsteps</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">}},</span><span style="color: #000000;">2000</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">maxsteps</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">}},</span><span style="color: #000000;">20000</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #000000;">maxsteps</span><span style="color: #0000FF;">({{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">}},</span><span style="color: #000000;">50000</span><span style="color: #0000FF;">)</span>
|
||||
<!--
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
from functools import lru_cache
|
||||
|
||||
|
||||
#%%
|
||||
|
||||
DIVS = {2, 3}
|
||||
SUBS = {1}
|
||||
|
||||
class Minrec():
|
||||
"Recursive, memoised minimised steps to 1"
|
||||
|
||||
def __init__(self, divs=DIVS, subs=SUBS):
|
||||
self.divs, self.subs = divs, subs
|
||||
|
||||
@lru_cache(maxsize=None)
|
||||
def _minrec(self, n):
|
||||
"Recursive, memoised"
|
||||
if n == 1:
|
||||
return 0, ['=1']
|
||||
possibles = {}
|
||||
for d in self.divs:
|
||||
if n % d == 0:
|
||||
possibles[f'/{d}=>{n // d:2}'] = self._minrec(n // d)
|
||||
for s in self.subs:
|
||||
if n > s:
|
||||
possibles[f'-{s}=>{n - s:2}'] = self._minrec(n - s)
|
||||
thiskind, (count, otherkinds) = min(possibles.items(), key=lambda x: x[1])
|
||||
ret = 1 + count, [thiskind] + otherkinds
|
||||
return ret
|
||||
|
||||
def __call__(self, n):
|
||||
"Recursive, memoised"
|
||||
ans = self._minrec(n)[1][:-1]
|
||||
return len(ans), ans
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
for DIVS, SUBS in [({2, 3}, {1}), ({2, 3}, {2})]:
|
||||
minrec = Minrec(DIVS, SUBS)
|
||||
print('\nMINIMUM STEPS TO 1: Recursive algorithm')
|
||||
print(' Possible divisors: ', DIVS)
|
||||
print(' Possible decrements:', SUBS)
|
||||
for n in range(1, 11):
|
||||
steps, how = minrec(n)
|
||||
print(f' minrec({n:2}) in {steps:2} by: ', ', '.join(how))
|
||||
|
||||
upto = 2000
|
||||
print(f'\n Those numbers up to {upto} that take the maximum, "minimal steps down to 1":')
|
||||
stepn = sorted((minrec(n)[0], n) for n in range(upto, 0, -1))
|
||||
mx = stepn[-1][0]
|
||||
ans = [x[1] for x in stepn if x[0] == mx]
|
||||
print(' Taking', mx, f'steps is/are the {len(ans)} numbers:',
|
||||
', '.join(str(n) for n in sorted(ans)))
|
||||
#print(minrec._minrec.cache_info())
|
||||
print()
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
class Mintab():
|
||||
"Tabulation, memoised minimised steps to 1"
|
||||
|
||||
def __init__(self, divs=DIVS, subs=SUBS):
|
||||
self.divs, self.subs = divs, subs
|
||||
self.table = None # Last tabulated table
|
||||
self.hows = None # Last tabulated sample steps
|
||||
|
||||
def _mintab(self, n):
|
||||
"Tabulation, memoised minimised steps to 1"
|
||||
divs, subs = self.divs, self.subs
|
||||
|
||||
table = [n + 2] * (n + 1) # sentinels
|
||||
table[1] = 0 # zero steps to 1 from 1
|
||||
how = [[''] for _ in range(n + 2)] # What steps are taken
|
||||
how[1] = ['=']
|
||||
for t in range(1, n):
|
||||
thisplus1 = table[t] + 1
|
||||
for d in divs:
|
||||
dt = d * t
|
||||
if dt <= n and thisplus1 < table[dt]:
|
||||
table[dt] = thisplus1
|
||||
how[dt] = how[t] + [f'/{d}=>{t:2}']
|
||||
for s in subs:
|
||||
st = s + t
|
||||
if st <= n and thisplus1 < table[st]:
|
||||
table[st] = thisplus1
|
||||
how[st] = how[t] + [f'-{s}=>{t:2}']
|
||||
self.table = table
|
||||
self.hows = [h[::-1][:-1] for h in how] # Order and trim
|
||||
return self.table, self.hows
|
||||
|
||||
def __call__(self, n):
|
||||
"Tabulation"
|
||||
table, hows = self._mintab(n)
|
||||
return table[n], hows[n]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
for DIVS, SUBS in [({2, 3}, {1}), ({2, 3}, {2})]:
|
||||
print('\nMINIMUM STEPS TO 1: Tabulation algorithm')
|
||||
print(' Possible divisors: ', DIVS)
|
||||
print(' Possible decrements:', SUBS)
|
||||
mintab = Mintab(DIVS, SUBS)
|
||||
mintab(10)
|
||||
table, hows = mintab.table, mintab.hows
|
||||
for n in range(1, 11):
|
||||
steps, how = table[n], hows[n]
|
||||
print(f' mintab({n:2}) in {steps:2} by: ', ', '.join(how))
|
||||
|
||||
for upto in [2000, 50_000]:
|
||||
mintab(upto)
|
||||
table = mintab.table
|
||||
print(f'\n Those numbers up to {upto} that take the maximum, "minimal steps down to 1":')
|
||||
mx = max(table[1:])
|
||||
ans = [n for n, steps in enumerate(table) if steps == mx]
|
||||
print(' Taking', mx, f'steps is/are the {len(ans)} numbers:',
|
||||
', '.join(str(n) for n in ans))
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
use Lingua::EN::Numbers;
|
||||
|
||||
for [2,3], 1, 2000,
|
||||
[2,3], 1, 50000,
|
||||
[2,3], 2, 2000,
|
||||
[2,3], 2, 50000
|
||||
-> @div, $sub, $limit {
|
||||
my %min = 1 => {:op(''), :v(1), :s(0)};
|
||||
(2..$limit).map( -> $n {
|
||||
my @ops;
|
||||
@ops.push: ($n / $_, "/$_") if $n %% $_ for @div;
|
||||
@ops.push: ($n - $sub, "-$sub") if $n > $sub;
|
||||
my $op = @ops.min( {%min{.[0]}<s>} );
|
||||
%min{$n} = {:op($op[1]), :v($op[0]), :s(1 + %min{$op[0]}<s>)};
|
||||
});
|
||||
|
||||
my $max = %min.max( {.value<s>} ).value<s>;
|
||||
my @max = %min.grep( {.value.<s> == $max} )».key.sort(+*);
|
||||
|
||||
if $limit == 2000 {
|
||||
say "\nDivisors: {@div.perl}, subtract: $sub";
|
||||
steps(1..10);
|
||||
}
|
||||
say "\nUp to {comma $limit} found {+@max} number{+@max == 1 ?? '' !! 's'} " ~
|
||||
"that require{+@max == 1 ?? 's' !! ''} at least $max steps.";
|
||||
steps(@max);
|
||||
|
||||
sub steps (*@list) {
|
||||
for @list -> $m {
|
||||
my @op;
|
||||
my $n = $m;
|
||||
while %min{$n}<s> {
|
||||
@op.push: "{%min{$n}<op>}=>{%min{$n}<v>}";
|
||||
$n = %min{$n}<v>;
|
||||
}
|
||||
say "($m) {%min{$m}<s>} steps: ", @op.join(', ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
func minToOne(divs: [Int], subs: [Int], upTo n: Int) -> ([Int], [[String]]) {
|
||||
var table = Array(repeating: n + 2, count: n + 1)
|
||||
var how = Array(repeating: [""], count: n + 2)
|
||||
|
||||
table[1] = 0
|
||||
how[1] = ["="]
|
||||
|
||||
for t in 1..<n {
|
||||
let thisPlus1 = table[t] + 1
|
||||
|
||||
for div in divs {
|
||||
let dt = div * t
|
||||
|
||||
if dt <= n && thisPlus1 < table[dt] {
|
||||
table[dt] = thisPlus1
|
||||
how[dt] = how[t] + ["/\(div)=> \(t)"]
|
||||
}
|
||||
}
|
||||
|
||||
for sub in subs {
|
||||
let st = sub + t
|
||||
|
||||
if st <= n && thisPlus1 < table[st] {
|
||||
table[st] = thisPlus1
|
||||
how[st] = how[t] + ["-\(sub)=> \(t)"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (table, how.map({ $0.reversed().dropLast() }))
|
||||
}
|
||||
|
||||
for (divs, subs) in [([2, 3], [1]), ([2, 3], [2])] {
|
||||
print("\nMINIMUM STEPS TO 1:")
|
||||
print(" Possible divisors: \(divs)")
|
||||
print(" Possible decrements: \(subs)")
|
||||
|
||||
let (table, hows) = minToOne(divs: divs, subs: subs, upTo: 10)
|
||||
|
||||
for n in 1...10 {
|
||||
print(" mintab( \(n)) in { \(table[n])} by: ", hows[n].joined(separator: ", "))
|
||||
}
|
||||
|
||||
for upTo in [2_000, 50_000] {
|
||||
print("\n Those numbers up to \(upTo) that take the maximum, \"minimal steps down to 1\":")
|
||||
let (table, _) = minToOne(divs: divs, subs: subs, upTo: upTo)
|
||||
let max = table.dropFirst().max()!
|
||||
let maxNs = table.enumerated().filter({ $0.element == max })
|
||||
|
||||
print(
|
||||
" Taking", max, "steps are the \(maxNs.count) numbers:",
|
||||
maxNs.map({ String($0.offset) }).joined(separator: ", ")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
import "/fmt" for Fmt
|
||||
|
||||
var limit = 50000
|
||||
var divs = []
|
||||
var subs = []
|
||||
var mins = []
|
||||
|
||||
// Assumes the numbers are presented in order up to 'limit'.
|
||||
var minsteps = Fn.new { |n|
|
||||
if (n == 1) {
|
||||
mins[1] = []
|
||||
return
|
||||
}
|
||||
var min = limit
|
||||
var p = 0
|
||||
var q = 0
|
||||
var op = ""
|
||||
for (div in divs) {
|
||||
if (n%div == 0) {
|
||||
var d = (n/div).floor
|
||||
var steps = mins[d].count + 1
|
||||
if (steps < min) {
|
||||
min = steps
|
||||
p = d
|
||||
q = div
|
||||
op = "/"
|
||||
}
|
||||
}
|
||||
}
|
||||
for (sub in subs) {
|
||||
var d = n - sub
|
||||
if (d >= 1) {
|
||||
var steps = mins[d].count + 1
|
||||
if (steps < min) {
|
||||
min = steps
|
||||
p = d
|
||||
q = sub
|
||||
op = "-"
|
||||
}
|
||||
}
|
||||
}
|
||||
mins[n].add("%(op)%(q) -> %(p)")
|
||||
mins[n].addAll(mins[p])
|
||||
}
|
||||
|
||||
for (r in 0..1) {
|
||||
divs = [2, 3]
|
||||
subs = (r == 0) ? [1] : [2]
|
||||
mins = List.filled(limit+1, null)
|
||||
for (i in 0..limit) mins[i] = []
|
||||
Fmt.print("With: Divisors: $n, Subtractors: $n =>", divs, subs)
|
||||
System.print(" Minimum number of steps to diminish the following numbers down to 1 is:")
|
||||
for (i in 1..limit) {
|
||||
minsteps.call(i)
|
||||
if (i <= 10) {
|
||||
var steps = mins[i].count
|
||||
var plural = (steps == 1) ? " " : "s"
|
||||
var mi = Fmt.v("s", 0, mins[i], 0, ", ", "")
|
||||
Fmt.print(" $2d: $d step$s: $s", i, steps, plural, mi)
|
||||
}
|
||||
}
|
||||
for (lim in [2000, 20000, 50000]) {
|
||||
var max = 0
|
||||
for (min in mins[0..lim]) {
|
||||
var m = min.count
|
||||
if (m > max) max = m
|
||||
}
|
||||
var maxs = []
|
||||
var i = 0
|
||||
for (min in mins[0..lim]) {
|
||||
if (min.count == max) maxs.add(i)
|
||||
i = i + 1
|
||||
}
|
||||
var nums = maxs.count
|
||||
var verb = (nums == 1) ? "is" : "are"
|
||||
var verb2 = (nums == 1) ? "has" : "have"
|
||||
var plural = (nums == 1) ? "": "s"
|
||||
Fmt.write(" There $s $d number$s in the range 1-$d ", verb, nums, plural, lim)
|
||||
Fmt.print("that $s maximum 'minimal steps' of $d:", verb2, max)
|
||||
System.print(" %(maxs)")
|
||||
}
|
||||
System.print()
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
int MinSteps, \minimal number of steps to get to 1
|
||||
Subtractor; \1 or 2
|
||||
char Ns(20000), Ops(20000), MinNs(20000), MinOps(20000);
|
||||
|
||||
proc Reduce(N, Step); \Reduce N to 1, recording minimum steps
|
||||
int N, Step, I;
|
||||
[if N = 1 then
|
||||
[if Step < MinSteps then
|
||||
[for I:= 0 to Step-1 do
|
||||
[MinOps(I):= Ops(I);
|
||||
MinNs(I):= Ns(I);
|
||||
];
|
||||
MinSteps:= Step;
|
||||
];
|
||||
];
|
||||
if Step >= MinSteps then return; \don't search further
|
||||
if rem(N/3) = 0 then
|
||||
[Ops(Step):= 3; Ns(Step):= N/3; Reduce(N/3, Step+1)];
|
||||
if rem(N/2) = 0 then
|
||||
[Ops(Step):= 2; Ns(Step):= N/2; Reduce(N/2, Step+1)];
|
||||
Ops(Step):= -Subtractor; Ns(Step):= N-Subtractor; Reduce(N-Subtractor, Step+1);
|
||||
]; \Reduce
|
||||
|
||||
proc ShowSteps(N); \Show minimal steps and how N steps to 1
|
||||
int N, I;
|
||||
[MinSteps:= $7FFF_FFFF;
|
||||
Reduce(N, 0);
|
||||
Text(0, "N = "); IntOut(0, N);
|
||||
Text(0, " takes "); IntOut(0, MinSteps); Text(0, " steps: N ");
|
||||
for I:= 0 to MinSteps-1 do
|
||||
[Text(0, if extend(MinOps(I)) < 0 then "-" else "/");
|
||||
IntOut(0, abs(extend(MinOps(I))));
|
||||
Text(0, "=>"); IntOut(0, MinNs(I)); Text(0, " ");
|
||||
];
|
||||
CrLf(0);
|
||||
]; \ShowSteps
|
||||
|
||||
proc ShowCount(Range); \Show count of maximum minimal steps and their Ns
|
||||
int Range;
|
||||
int N, MaxSteps;
|
||||
[MaxSteps:= 0; \find maximum number of minimum steps
|
||||
for N:= 1 to Range do
|
||||
[MinSteps:= $7FFF_FFFF;
|
||||
Reduce(N, 0);
|
||||
if MinSteps > MaxSteps then
|
||||
MaxSteps:= MinSteps;
|
||||
];
|
||||
Text(0, "Maximum steps: "); IntOut(0, MaxSteps); Text(0, " for N = ");
|
||||
for N:= 1 to Range do \show numbers (Ns) for Maximum steps
|
||||
[MinSteps:= $7FFF_FFFF;
|
||||
Reduce(N, 0);
|
||||
if MinSteps = MaxSteps then
|
||||
[IntOut(0, N); Text(0, " ");
|
||||
];
|
||||
];
|
||||
CrLf(0);
|
||||
]; \ShowCount
|
||||
|
||||
int N;
|
||||
[Subtractor:= 1; \1.
|
||||
for N:= 1 to 10 do ShowSteps(N);
|
||||
ShowCount(2000); \2.
|
||||
ShowCount(20_000); \2a.
|
||||
Subtractor:= 2; \3.
|
||||
for N:= 1 to 10 do ShowSteps(N);
|
||||
ShowCount(2000); \4.
|
||||
ShowCount(20_000); \4a.
|
||||
]
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
var minCache; // (val:(newVal,op,steps))
|
||||
fcn buildCache(N,D,S){
|
||||
minCache=Dictionary(1,T(1,"",0));
|
||||
foreach n in ([2..N]){
|
||||
ops:=List();
|
||||
foreach d in (D){ if(n%d==0) ops.append(T(n/d, String("/",d))) }
|
||||
foreach s in (S){ if(n>s) ops.append(T(n - s,String("-",s))) }
|
||||
mcv:=fcn(op){ minCache[op[0]][2] }; // !ACK!, dig out steps
|
||||
v,op := ops.reduce( // find min steps to get to op
|
||||
'wrap(vo1,vo2){ if(mcv(vo1)<mcv(vo2)) vo1 else vo2 });
|
||||
minCache[n]=T(v, op, 1 + minCache[v][2]) // this many steps to get to n
|
||||
}
|
||||
}
|
||||
fcn stepsToOne(N){ // D & S are determined by minCache
|
||||
ops,steps := Sink(String).write(N), minCache[N][2];
|
||||
do(steps){ v,o,s := minCache[N]; ops.write(" ",o,"-->",N=v); }
|
||||
return(steps,ops.close())
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
MAX, D,S := 50_000, T(2,3), T(1);
|
||||
buildCache(MAX,D,S);
|
||||
|
||||
do(2){
|
||||
println("\nDivisors: %s, subtracters: %s".fmt(D.concat(","), S.concat(",")));
|
||||
foreach n in ([1..10]){ println("%2d: %d steps: %s".fmt(n,stepsToOne(n).xplode())) }
|
||||
|
||||
maxSteps:=minCache.reduce(fcn(mkv,kv){ if(mkv[1][2]>kv[1][2]) mkv else kv })[1][2];
|
||||
biggies :=minCache.filter('wrap(kv){ kv[1][2]==maxSteps }).pump(List,fcn(kv){ kv[0].toInt() }).sort();
|
||||
println("\nBelow %,d, found %d numbers that require %d steps (the mostest)."
|
||||
.fmt(MAX,biggies.len(),maxSteps));
|
||||
foreach n in (biggies){ println("%,6d: %d steps: %s".fmt(n,stepsToOne(n).xplode())) }
|
||||
|
||||
S=T(2); buildCache(MAX,D,S);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue