Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions algorithms/coin_change.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#import "../lib/style.typ": *
#import "../lib/mapcode.typ": *

== Coin Change (Minimum Coins)
#set math.equation(numbering: none)

Compute the minimum number of coins needed to make a target amount.

Formal definition:
$
"CC"(0) &= 0\
"CC"(n) &= min_(c in "coins", c <= n) (1 + "CC"(n-c)) quad "for" n > 0
$

Example: coins = [1,3,4], amount = 6
Minimum coins = 2 (using 3+3)

*As mapcode:*

_primitives_: `min` and `add`($+$) are strict. i.e min and add on $bot$ is undefined.

$
I = "amount": NN quad quad quad X &= [0.."amount"] -> NN_bot quad quad quad A = NN\
rho("amount") &= {i -> bot | i in [0.."amount"], i > 0} union {0 -> 0}\
F(x)[i] &= cases(
0 & "if" i = 0,
min_(c in "coins", c <= i) {1 + x[i - c]} & "if" i > 0 "and deps defined",
bot & "otherwise"
)\
pi(x) &= x["amount"]
$

#let coins = (1, 3, 4);
#let amount = 6;
#figure(
caption: [Coin Change computation using mapcode for amount = #amount, coins = #coins],
$
#{
let rho = (amount) => {
let x = ()
for i in range(0, amount + 1) {
if i == 0 {
x.push(0)
} else {
x.push(none)
}
}
x
}

let F_i = (x) => ((i,)) => {
if i == 0 {
0
} else {
let candidates = ()
for c in coins {
if c <= i and x.at(i - c) != none {
candidates.push(x.at(i - c) + 1)
}
}
if candidates.len() > 0 {
calc.min(..candidates)
} else {
none
}
}
}
let F = map_tensor(F_i, dim: 1)

let pi = (i) => (x) => x.at(i)

let X_h = (x, diff_mask: none) => {
let cells = x.enumerate().map(((i, x_i)) => {
let val = if x_i != none {[$#x_i$]} else {[$bot$]}
if diff_mask != none and diff_mask.at(i) {
rect(fill: yellow.transparentize(70%), inset: 2pt)[$#val$]
} else {
rect(stroke: none, inset: 2pt)[$#val$]
}
})
$vec(delim: "[", ..cells)$
}

mapcode-viz(
rho, F, pi(amount),
X_h: X_h,
pi_name: [$pi (#amount)$],
group-size: calc.min(7, amount + 1),
cell-size: 10mm, scale-fig: 85%
)(amount)
}
$
)
101 changes: 101 additions & 0 deletions algorithms/lis.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#import "../lib/style.typ": *
#import "../lib/mapcode.typ": *

== Longest Increasing Subsequence (LIS)
#set math.equation(numbering: none)

Compute the length of the longest increasing subsequence in an array.

Formal definition:
$
"LIS"(i) = cases(
1 & "if" i = 0,
1 + max_(j < i, A[j] < A[i]) "LIS"(j) & "if" i > 0 "and valid j exists",
1 & "otherwise"
)
$

Example: A = [10, 9, 2, 5, 3, 7, 101]
LIS length = 4 (subsequence: [2, 3, 7, 101] or [2, 5, 7, 101])

*As mapcode:*

_primitives_: `max` and `add`($+$) are strict. i.e max and add on $bot$ is undefined.

$
I = (n: NN, A: "array") quad quad quad X &= [0..n-1] -> NN_bot quad quad quad A = NN\
rho(n, A) &= {i -> 1 | i in [0..n-1]}\
F(x)[i] &= cases(
1 & "if" i = 0,
1 + max_(j < i, A[j] < A[i]) {x[j]} & "if valid j and deps defined",
1 & "otherwise"
)\
pi(x) &= max_(i) x[i]
$

#let arr = (10, 9, 2, 5, 3, 7, 101);
#let n = arr.len();
#figure(
caption: [LIS computation using mapcode for array = #arr],
$
#{
let rho = (n) => {
let x = ()
for i in range(0, n) {
x.push(1)
}
x
}

let F_i = (x) => ((i,)) => {
if i == 0 {
1
} else {
let max_len = 1
for j in range(0, i) {
if arr.at(j) < arr.at(i) and x.at(j) != none {
max_len = calc.max(max_len, x.at(j) + 1)
}
}
max_len
}
}
let F = map_tensor(F_i, dim: 1)

let pi = (n) => (x) => {
let max_val = 0
for val in x {
if val != none {
max_val = calc.max(max_val, val)
}
}
max_val
}

let X_h = (x, diff_mask: none) => {
let cells = x.enumerate().map(((i, x_i)) => {
let val = if x_i != none {[$#x_i$]} else {[$bot$]}
let arr_val = arr.at(i)
if diff_mask != none and diff_mask.at(i) {
rect(fill: yellow.transparentize(70%), inset: 2pt)[
$#arr_val: #val$
]
} else {
rect(stroke: none, inset: 2pt)[
$#arr_val: #val$
]
}
})
$vec(delim: "[", ..cells)$
}

mapcode-viz(
rho, F, pi(n),
X_h: X_h,
pi_name: [$max_i x[i]$],
group-size: calc.min(7, n),
cell-size: 12mm, scale-fig: 80%
)(n)
}
$
)
Binary file added main.pdf
Binary file not shown.
4 changes: 4 additions & 0 deletions main.typ
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,7 @@ All primitives are _strict_ meaning they do not allow for undefined values (i.e.
#include "algorithms/LongestCommonSubsequence.typ"
#pagebreak()
#include "algorithms/leetcode/P2_add-two-numbers.typ"
#pagebreak()
#include "algorithms/lis.typ"
#pagebreak()
#include "algorithms/coin_change.typ"