Counting coins in APL - greedy

The function Count below calculates the minimal number of coins which sums up to a given amount.
∇ R ← d AppendQuotRem qrs; oldR; q; r
oldR ← 2 ⊃ (⍴qrs) ⊃ qrs
q ← ⌊oldR ÷ d
r ← oldR - d × q
R ← qrs , ,⊂(q r)
∇
∇ R ← Count amount; ds; qrs; qs
ds ← 1 5 10 25 50 ⍝ coin denominations in cents
qrs ← ⊃AppendQuotRem/ ds , ⊂,⊂(0 amount)
qs ← 1 ⊃¨ qrs
R ← ds ,[0.5] ⌽1 ↓ qs
∇
For each denomination I calculate a quotient and a remainder. The remainder is used in the calculation involving the next denomination. Is there a shorter and/or more straight forward way to solve the problem?

The change-making problem is actually quite hard. A full APL approach is included in the dfns workspace.
Your algorithm is greedy, which gives the wrong result for certain sets sets of coin denominations. It just happens to work out with the set you use in your example. Let's modify your Count function:
∇ R ← Count134 amount; ds; qrs; qs
ds ← 1 3 4 ⍝ coin denominations in cents
qrs ← ⊃AppendQuotRem/ ds , ⊂,⊂(0 amount)
qs ← 1 ⊃¨ qrs
R ← ds ,[0.5] ⌽1 ↓ qs
∇
Count134 6
1 3 4
2 0 1
This uses three coins, but two 3-cent coins is the correct answer:
1 3 4
0 2 0
That being said, common coinage systems are designed such that a greedy algorithm will produce the optimal result. Here is thus a simplification of your code:
∇ R ← d AppendQuotRem qrs; oldR; q; r
oldR ← 1 ↑ qrs
q ← ⌊oldR ÷ d
r ← d | oldR
R ← r , q , 1 ↓ qrs
∇
∇ R ← Count amount; ds
ds ← 1 5 10 25 50 ⍝ coin denominations in cents
R ← ds ,[0.5] ⊃AppendQuotRem/ 1 ↓ ds , amount
∇
Try it online!

Greedy algoritm, where money value are 100 50 20 10 5 1 unit.
∇r←Greedy w;i;d;k;x;l
r←⍬⋄i←1⋄d←100 50 20 10 5 1⋄l←≢d
r←r,k←⌊w÷x←d[i]⋄w-←k×x⋄→2×⍳l≥i+←1
r←2 l⍴d,r
∇
Prova←{+/⍵[1;]×⍵[2;]}
m←Greedy 125
m
100 50 20 10 5 1
1 0 1 0 1 0
Prova m
125

Related

Find column number of last match in a row in sheets

In this table it's easy to find that column E is the first match for the value 3.
How do I find the column of the last match of 3 which will be column I
A B C D E F G H I J K L
6 6 9 9 3 3 2 2 3 1 1 1
Use this formula
=ArrayFormula(Substitute(Address(1,MAX(IF(REGEXMATCH(A1:L1,3&"")<>TRUE,,COLUMN(A1:L1))),4),"1",""))
try:
=SUBSTITUTE(ADDRESS(2, XMATCH(3, A2:P2,, -1), 4), 2, )
=ADDRESS(2, XMATCH(3, A2:P2,, -1), 4)
=XLOOKUP(3, A2:P2, A1:P1,,, -1)
XMATCH has a reverse search feature. Set search_mode top -1 to activate:
=INDEX(1:1,XMATCH(3,2:2,,-1))
(A1)A
B
C
D
E
F
G
H
I
J
K
L
6
6
9
9
3
3
2
2
3
1
1
1
Result:
I

Solving Equations with (wx)Maxima: Control stack exhausted

Solving Equations with (wx)Maxima: Control stack exhausted
I'm trying to solve equations with (wx)Maxima: formulate the equation, then let it insert the variables and solve the equation for the missing variable. But I'm having a hard time. Somehow it's having problems in the last line:
Control stack exhausted (no more space for function call frames).
This is probably due to heavily nested or infinitely recursive function
calls, or a tail call that SBCL cannot or has not optimized away.
That's my code:
kill(all);
load(physical_constants);
load(unit);
setunits([kg,m,s,N]);
showtime: false;
α: 30*%pi/180;
/*α: 30*°;*/
masse: 1000*kg;
g: 9.80665*m/(s*s);
b: 0.3*m;
B: 0.5*m;
L: 0.1*m;
F_g: masse*g;
F_H: masse * g;
kill(S, x);
S: solve(0=F_H-2*x*sin(α), x);
S: assoc(x, S);
kill(H, x);
H: solve(0=-F_g+2*x, x);
H: assoc(x, H);
kill(Ly, x);
Ly: solve(tan(α)=x/(B/2), x);
Ly: assoc(x, Ly);
kill(FN, x);
FN: solve(0=H*B/2-x*(L+Ly)+S*sin(α)*B/2+S*cos(α)*Ly, x);
FN: assoc(x, FN);
If I calculate it "directly", it works though:
kill(all);
load(physical_constants);
load(unit);
setunits([kg,m,s,N]);
showtime: false;
kill(FN, x);
FN: solve([α=30*%pi/180, H=196133/40*N,
B=0.5*m, L=0.1*m,
Ly=sqrt(3)/12*m, S=196133/20*N,
0=H*B/2-x*(L+Ly)+S*sin(α)*B/2+S*cos(α)*Ly],
[x, α, H, B, L, Ly, S]);
FN: assoc(x, FN[1]);
FN: float(FN);
(FN) 1934473685/128529*N
Unfortunately the unit package has not been updated in some time. I'll suggest to use instead the package ezunits, in which dimensional quantities are represented with a back quote. To solve equations, try dimensionally which goes through some gyrations to help other functions with dimensional quantities, e.g. dimensionally (solve (...)). (Note that dimensionally isn't documented, I'm sorry for the shortcoming.)
I've modified your program a little to remove some unneeded stuff and also to use rational numbers instead of floats; Maxima is generally more comfortable with rationals and integers than with floats. Here is the program:
linel: 65 $
load(ezunits) $
α: 30*%pi/180;
masse: 1000`kg;
g: rationalize(9.80665)`m/(s*s);
b: 3/10`m;
B: 5/10`m;
L: 1/10`m;
F_g: masse*g;
F_H: masse * g;
S: dimensionally (solve(0=F_H-2*x*sin(α), x));
S: assoc(x, S);
Ly: dimensionally (solve(tan(α)=x/(B/2), x));
Ly: assoc(x, Ly);
FN: dimensionally (solve(0=H*B/2-x*(L+Ly)+S*sin(α)*B/2+S*cos(α)*Ly, x));
FN: assoc(x, FN);
subst (x = S, F_H-2*x*sin(α));
subst (x = Ly, tan(α)=x/(B/2));
subst (x = FN, H*B/2-x*(L+Ly)+S*sin(α)*B/2+S*cos(α)*Ly);
ratsimp (expand (%));
and here is the output I get. Note that I substituted the solutions back into the equations to verify them. It looks like it worked as expected.
(%i2) linel:65
(%i3) load(ezunits)
(%i4) α:(30*%pi)/180
%pi
(%o4) ---
6
(%i5) masse:1000 ` kg
(%o5) 1000 ` kg
(%i6) g:rationalize(9.80665) ` m/(s*s)
5520653160719109 m
(%o6) ---------------- ` --
562949953421312 2
s
(%i7) b:3/10 ` m
3
(%o7) -- ` m
10
(%i8) B:5/10 ` m
1
(%o8) - ` m
2
(%i9) L:1/10 ` m
1
(%o9) -- ` m
10
(%i10) F_g:masse*g
690081645089888625 kg m
(%o10) ------------------ ` ----
70368744177664 2
s
(%i11) F_H:masse*g
690081645089888625 kg m
(%o11) ------------------ ` ----
70368744177664 2
s
(%i12) S:dimensionally(solve(0 = F_H-2*x*sin(α),x))
690081645089888625 kg m
(%o12) [x = ------------------ ` ----]
70368744177664 2
s
(%i13) S:assoc(x,S)
690081645089888625 kg m
(%o13) ------------------ ` ----
70368744177664 2
s
(%i14) Ly:dimensionally(solve(tan(α) = x/(B/2),x))
1
(%o14) [x = --------- ` m]
4 sqrt(3)
(%i15) Ly:assoc(x,Ly)
1
(%o15) --------- ` m
4 sqrt(3)
(%i16) FN:dimensionally(solve(0 = (H*B)/2-x*(L+Ly)
+(S*sin(α)*B)/2
+S*cos(α)*Ly,x))
1 1
(%o16) [x = (----------------------------------------- ` --)
140737488355328 sqrt(3) + 351843720888320 2
s
2
(351843720888320 sqrt(3) H ` s
3/2
+ 1150136075149814375 3 ` kg m)]
(%i17) FN:assoc(x,FN)
1 1
(%o17) (----------------------------------------- ` --)
140737488355328 sqrt(3) + 351843720888320 2
s
2
(351843720888320 sqrt(3) H ` s
3/2
+ 1150136075149814375 3 ` kg m)
(%i18) subst(x = S,F_H-2*x*sin(α))
kg m
(%o18) 0 ` ----
2
s
(%i19) subst(x = Ly,tan(α) = x/(B/2))
1 1
(%o19) ------- = -------
sqrt(3) sqrt(3)
(%i20) subst(x = FN,(H*B)/2-x*(L+Ly)+(S*sin(α)*B)/2+S*cos(α)*Ly)
1 1
(- ---------) - --
4 sqrt(3) 10 1
(%o20) ((----------------------------------------- ` --)
140737488355328 sqrt(3) + 351843720888320 2
s
2
(351843720888320 sqrt(3) H ` s
3/2 H
+ 1150136075149814375 3 ` kg m) + -) ` m
4
2
690081645089888625 kg m
+ ------------------ ` -----
281474976710656 2
s
(%i21) ratsimp(expand(%))
2
kg m
(%o21) 0 ` -----
2
s
EDIT. About converting kg*m/s^2 to N, you can apply the double back quote operator. For example:
(%i25) F_g `` N
690081645089888625
(%o25) ------------------ ` N
70368744177664
By the way, to convert back to floats, you can apply float:
(%i26) float(%)
(%o26) 9806.649999999998 ` N
Converting FN to N is a little more involved, since it's a more complex expression, especially because of H which doesn't have units attached to it yet. Some inspection seems to show the units of H must be kg*m/s^2. I'll apply declare_units to say that's what are the units of H. Then I'll convert FN to N.
(%i27) declare_units(H,(kg*m)/s^2)
kg m
(%o27) ----
2
s
(%i28) FN `` N
351843720888320 sqrt(3) qty(H)
(%o28) (-----------------------------------------
140737488355328 sqrt(3) + 351843720888320
3/2
1150136075149814375 3
+ -----------------------------------------) ` N
140737488355328 sqrt(3) + 351843720888320
(%i29) float(%)
(%o29) (1.023174629940149 qty(H) + 10033.91548470256) ` N
The notation qty(H) represents the unspecified quantity of H. One could also just subst(H = 100 ` kg*m/s^2, FN) (or any quantity, not just 100) and go from there.

Taylor series expansion in maxima

How to expand taylor series/polynomials about Q=0 , and then extract coefficients as a list
example :
taylor ( (sin(q)), q, 0, 9); //taylor expansion for first 9 terms gives the next line
(%o1)/T/ q\-q^3/6+q^5/120\-q^7/5040+q^9/362880+...
then using coeff ((%o1), q ^n); gives me the coefficient at n only, what i want is a list for all the coefficients of that expression
Try coeff plus makelist, e.g. something like: makelist(coeff(%o1, q, n), n, 0, 9);
Edit:
I see now that I misread your question and there is already an answer. Nevertheless I will keep it because it is related to your question.
Use powerseries instead of taylor:
(%i1) expr:powerseries(sin(x),x,0);
inf
==== i2 2 i2 + 1
\ (- 1) x
(%o1) > -----------------
/ (2 i2 + 1)!
====
i2 = 0
You can access the coefficient by the args or part function
(%i2) op(expr);
(%o2) sum
(%i3) args(expr);
i2 2 i2 + 1
(- 1) x
(%o3) [-----------------, i2, 0, inf]
(2 i2 + 1)!
(%i4) part(expr,1);
i2 2 i2 + 1
(- 1) x
(%o4) -----------------
(2 i2 + 1)!
(%i5) args(expr)[1];
i2 2 i2 + 1
(- 1) x
(%o5) -----------------
(2 i2 + 1)!
If you want to change the index variable:
(%i6) niceindices(expr),niceindicespref=[n];
inf
==== n 2 n + 1
\ (- 1) x
(%o6) > ---------------
/ (2 n + 1)!
====
n = 0

KDB How to join tables with different column names

If I have the following tables:
t1:([] c1: 1 2 3; c2: 120 234 876)
t2:([] cd1:1 2; d: 999 899)
How can I join tables where t1.c1 = t2.cd2, where c1 and cd2 are not linked columns?
You're looking to use a left join lj as follows:
q)t1: ([] c1: 1 2 3; c2: 120 234 876)
q)t2:([] cd1:1 2; d: 999 899)
q)t1 lj 1!`c1 xcol t2
c1 c2 d
----------
1 120 999
2 234 899
3 876
where we use xcol to rename the column cd1 in t2 to match c1 in t1.
You can read more on joins at https://code.kx.com/q/ref/joins/

Algorithm to add two digits to the end of a number to calculate a specific modulus?

So, lets say I have a number 123456. 123456 % 97 = 72. How can I determine what two digits need to be added to the end of 123456 such that the new number % 97 = 1? Note--it must always be two digits.
For example, 12345676 % 97 = 1. In this case, I need to add the digits "76" to the end of the number.
(This is for IBAN number calculation.)
x = 123456
x = x * 100
newX = x + 1 + 97 - (x % 97)
Edit: put the 100 in the wrong place
You calc the modulo of 12345600 to 97 and add (97 - that + 1) to that number.
So you get what RoBorg explained whay cleaner above :)
This is the equation that that you need
X = Y -(Number*100 mod y) - 1
where:
Number = 123456
Y = 97
X the number you need
Let’s say we have to receive the number containing 12 digits.
Step 1:
Write any random number of 10 digits, i.e. 2 digits less than needed, e.g. 1234567890 – this is X
Step 2:
X * 100 = 123456789000.
‘123456789000’ - this is Y
Step 3:
Y / 97 = '1272750402.061856'.
'06' – this is Z
Step 4:
97 – Z + 1 = 92.
'92' – this is W
Step 5:
Final Deal Number is X followed by W, i.e. '123456789092'
Examples of accepted numbers:
100000000093
100000000190
100000000287
Etc.
Modulo arithmetic is really not that different from regular arithmetic. The key to solving the kind of problem that you're having is to realize that what you would normally do to solve that problem is still valid (in what follows, any mention of number means integer number):
Say you have
15 + x = 20
The way that you solve this is by realizing that the inverse of 15 under regular addition is -15 then you can write (exploiting commutativity and associativity as we naturally do)
15 + x + (-15) = (15 + (-15)) + x = 0 + x = x = 20 + (-15) = 5
so that your answer is x = 5
Now on to your problem.
Say that N and M are known, and you're looking for x under addition modulo k:
( N + x ) mod k = M
First realize that
( N + x ) mod k = ( ( N mod k ) + ( x mod k ) ) mod k
and for the problem to make sense
M mod k = M
and
x mod k = x
so that by letting
N mod k = N_k
and
( a + b ) mod k = a +_k b
you have
N_k +_k x = M
which means that what you need is the inverse of N_k under +_k. This is actually pretty simple because the inverse under +_k is whatever satisfies this equation:
N_k +_k ("-N_k") = 0
which is actually pretty simple because for a number y such that 0 <= y < k
(y + (k - y)) mod k = k mod k = 0
so that
"-N_k" = (k-N_k)
and then
N_k +_k x +_k "-N_k" = N_k +_k "-N_k" +_k x = 0 +_k x = x = M +_k "-N_k" = M +_k ( k - N_k )
so that the solution to
( N + x ) mod k = M
is
x = ( M + ( k - ( N mod k ) ) ) mod k
and for your problem in particular
( 12345600 + x ) % 97 = 1
is solved by
x = ( 1 + ( 97 - ( 12345600 mod 97 ) ) ) mod 97 = 76
Do notice that the requirement that you solution always have two digits is built in as long as k < 100

Resources