From 2b5882e1cd118b5ec5ced7ac2ae8398c5c8eae02 Mon Sep 17 00:00:00 2001 From: miryala10sathvika Date: Sat, 15 Nov 2025 23:04:28 +0530 Subject: [PATCH 1/3] adding code files to pull --- algorithms/ackermann.typ | 0 algorithms/equal_sum_subset.typ | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 algorithms/ackermann.typ create mode 100644 algorithms/equal_sum_subset.typ diff --git a/algorithms/ackermann.typ b/algorithms/ackermann.typ new file mode 100644 index 0000000..e69de29 diff --git a/algorithms/equal_sum_subset.typ b/algorithms/equal_sum_subset.typ new file mode 100644 index 0000000..e69de29 From d4f108dfc12bd9ac16f30bb38f7826cb07760249 Mon Sep 17 00:00:00 2001 From: miryala10sathvika Date: Sun, 16 Nov 2025 19:31:41 +0530 Subject: [PATCH 2/3] commiting first version --- algorithms/ackermann.typ | 0 algorithms/decode_ways.typ | 264 ++++++++++++++++++++++++++++++++ algorithms/equal_sum_subset.typ | 178 +++++++++++++++++++++ algorithms/fibonacci.typ | 2 +- 4 files changed, 443 insertions(+), 1 deletion(-) delete mode 100644 algorithms/ackermann.typ create mode 100644 algorithms/decode_ways.typ diff --git a/algorithms/ackermann.typ b/algorithms/ackermann.typ deleted file mode 100644 index e69de29..0000000 diff --git a/algorithms/decode_ways.typ b/algorithms/decode_ways.typ new file mode 100644 index 0000000..d085e69 --- /dev/null +++ b/algorithms/decode_ways.typ @@ -0,0 +1,264 @@ +#import "../lib/style.typ": * +#import "../lib/mapcode.typ": * + +== Decode Ways + +Count the number of ways to decode a string of digits, where digits map to letters ('1' = 'A', '2' = 'B', ..., '26' = 'Z'). + +*Key Rules:* +- Single digit: '1'-'9' → valid (not '0') +- Two digits: '10'-'26' → valid +- Leading '0' → invalid + +*Recursive Formula:* +$ +"dp"[i] = cases( + 1 & "if " i = 0, + "dp"[i-1] & "if " s[i-1] != '0' "(single valid only)", + "dp"[i-2] & "if " s[i-1] = '0' and 10 <= s[i-2:i] <= 26 "(double only)", + "dp"[i-1] + "dp"[i-2] & "if both valid" +) +$ + +*As mapcode:* + +_primitives_: `add`($+$), `int`, `geq`($>=$), `leq`($<=$), `neq`($!=$) are strict. + +$ +I = s:"String" quad quad quad +&n = |s|\ +X_s &= [0..n] -> NN_bot quad quad quad +A = NN\ +rho(s) & = { i -> bot | i in {0 dots n}} \ +F(x_i) & = cases( + 1 & "if " i = 0, + 1 & "if " i = 1 and s[0] != '0', + 0 & "if " i = 1 and s[0] = '0', + "compute"(i) & "if " i >= 2 + )\ +pi(x) & = x_n +$ + +where $"compute"(i)$ considers both single-digit and two-digit decodings. + +#let examples = ( + ("12", "AB or L"), + ("226", "BZ, VF, or BBF"), + ("06", "Invalid"), + ("27", "BG only"), + ("11106", "AAJF or KJF"), + ("1201234", "Multiple ways"), +); + +#figure( + caption: [Decode Ways - Summary of Examples], + table( + columns: (auto, auto, auto, auto), + align: center + horizon, + stroke: 0.5pt, + inset: 8pt, + + table.cell(fill: gray.lighten(60%))[*String*], + table.cell(fill: gray.lighten(60%))[*dp Array*], + table.cell(fill: gray.lighten(60%))[*Result*], + table.cell(fill: gray.lighten(60%))[*Decodings*], + + ..examples.map(((s, desc)) => { + let n = s.len() + + // Compute DP array + let dp = (1,) + + // dp[1] + if s.at(0) == "0" { + dp.push(0) + } else { + dp.push(1) + } + + // dp[2..n] + for i in range(2, n + 1) { + let ways = 0 + + // Single digit + if s.at(i - 1) != "0" { + ways = ways + dp.at(i - 1) + } + + // Two digits + let two_str = s.slice(i - 2, i) + let val = int(two_str) + if val >= 10 and val <= 26 { + ways = ways + dp.at(i - 2) + } + + dp.push(ways) + } + + let result = dp.at(n) + let result_color = if result == 0 { red } else { green } + + ( + [*#s*], + [#dp.map(v => str(v)).join(", ")], + text(fill: result_color, weight: "bold")[#result], + [#desc], + ) + }).flatten() + ) +) + +// Larger example: "11106" +#let inst_s = "11106"; +#let inst_n = inst_s.len(); +#figure( + caption: [Detailed trace for s = "#inst_s"], +$#{ + let s = inst_s + let n = s.len() + + let rho = (s) => { + let x = () + for i in range(0, n + 1) { + x.push(none) + } + x + } + + let is_valid_two_digit = (s, i) => { + if i < 2 { return false } + let two_digit_str = s.slice(i - 2, i) + let val = int(two_digit_str) + val >= 10 and val <= 26 + } + + let F_i = (x) => ((i,)) => { + if i == 0 { + 1 + } else if i == 1 { + if s.at(0) == "0" { 0 } else { 1 } + } else { + if x.at(i - 1) == none or x.at(i - 2) == none { + return none + } + + let ways = 0 + if s.at(i - 1) != "0" { + ways = ways + x.at(i - 1) + } + if is_valid_two_digit(s, i) { + ways = ways + x.at(i - 2) + } + ways + } + } + + let F = map_tensor(F_i, dim: 1) + let pi = (n) => (x) => x.at(n) + + 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(n), + X_h: X_h, + pi_name: $pi$, + group-size: calc.min(6, n + 1), + cell-size: 12mm, + scale-fig: 95% + )(s) +} +$ +) + +// Even larger example: "1201234" +#let inst_s2 = "1201234"; +#let inst_n2 = inst_s2.len(); +#figure( + caption: [Detailed trace for s = "#inst_s2" (larger example)], +$#{ + let s = inst_s2 + let n = s.len() + + let rho = (s) => { + let x = () + for i in range(0, n + 1) { + x.push(none) + } + x + } + + let is_valid_two_digit = (s, i) => { + if i < 2 { return false } + let two_digit_str = s.slice(i - 2, i) + let val = int(two_digit_str) + val >= 10 and val <= 26 + } + + let F_i = (x) => ((i,)) => { + if i == 0 { + 1 + } else if i == 1 { + if s.at(0) == "0" { 0 } else { 1 } + } else { + if x.at(i - 1) == none or x.at(i - 2) == none { + return none + } + + let ways = 0 + if s.at(i - 1) != "0" { + ways = ways + x.at(i - 1) + } + if is_valid_two_digit(s, i) { + ways = ways + x.at(i - 2) + } + ways + } + } + + let F = map_tensor(F_i, dim: 1) + let pi = (n) => (x) => x.at(n) + + 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(n), + X_h: X_h, + pi_name: $pi$, + group-size: calc.min(8, n + 1), + cell-size: 10mm, + scale-fig: 90% + )(s) +} +$ +) + +*Interpretation for s = "#inst_s":* +- dp[0] = 1: "" (empty) → 1 way +- dp[1] = 1: "1" → 1 way (A) +- dp[2] = 2: "11" → 2 ways (AA, K) +- dp[3] = 2: "111" → 2 ways (AAA, AK, KA - but limited by previous) +- dp[4] = 1: "1110" → 1 way (only "10" is valid for the "0") +- dp[5] = 2: "11106" → 2 ways (AAJF, KJF) + +*Interpretation for s = "#inst_s2":* +The string "1201234" has multiple valid decodings due to various combinations of single and double-digit interpretations. \ No newline at end of file diff --git a/algorithms/equal_sum_subset.typ b/algorithms/equal_sum_subset.typ index e69de29..b9f5b6c 100644 --- a/algorithms/equal_sum_subset.typ +++ b/algorithms/equal_sum_subset.typ @@ -0,0 +1,178 @@ +#import "../lib/style.typ": * +#import "../lib/mapcode.typ": * + +== Partition Equal Subset Sum + +Determine if an array can be partitioned into two subsets with equal sum. + +Formal definition: +$ +"dp"[i][s] = cases( + "true" & "if " s = 0, + "false" & "if " i = 0 and s > 0, + "dp"[i-1][s] & "if " "nums"[i-1] > s, + "dp"[i-1][s] or "dp"[i-1][s - "nums"[i-1]] & "otherwise" +) +$ + +Example: +- nums = [1, 2, 5, 2] → true (partitions: [1, 2, 2] and [5]) +- nums = [1, 2, 5, 2] → false + +*As mapcode:* + +_primitives_: `or`($or$), `sum`, `div`($div$) + +$ +I = "nums":["NN"] quad quad quad +&"target" = sum("nums") div 2, n = |"nums"|\ +X_("nums") &= [0..n] times [0.."target"] -> {"true", "false"}_bot quad quad quad +A = {"true", "false"}\ +rho("nums") & = { (i,s) -> bot | i in {0 dots n}, s in {0 dots "target"}} \ +F_("nums")(x_(i,s)) & = cases( + "true" & "if " s = 0, + "false" & "if " i = 0 and s > 0, + x_(i-1,s) & "if " "nums"[i-1] > s, + x_(i-1,s) or x_(i-1,s-"nums"[i-1]) & "otherwise" + )\ +pi_("nums") (x) & = x_(n,"target") +$ + +#let inst_nums = (1, 2, 5, 2); +#let total_sum = inst_nums.sum(); +#let inst_target = 5; +#let n = inst_nums.len(); + +#figure( + caption: [Partition Equal Subset Sum using mapcode for nums = $(#inst_nums.map(str).join(", "))$, target = $#inst_target$], +$#{ + if inst_target != -1 { + let nums = inst_nums; // <--- ADDED SEMICOLON + let target = inst_target; // <--- ADDED SEMICOLON + + let rho = ((nums, target)) => { + let x = () + for i in range(0, n + 1) { + let row = () + for s in range(0, target + 1) { + row.push(none) + } + x.push(row) + } + x + } + + let F_i = ((nums)) => (x) => ((i, s)) => { + // Base case: sum 0 is always achievable + if s == 0 { + true + } else if i == 0 { + // Base case: no items, sum > 0 is not achievable + false + } else { + let num = nums.at(i - 1) + + // If current number is larger than target sum + if num > s { + // Can't include it, inherit from previous + let prev = x.at(i - 1).at(s) + if prev != none { + prev + } else { + none + } + } else { + // Can either include or exclude + let exclude = x.at(i - 1).at(s) + + // Check bounds before accessing + let include_val = none + if s >= num and (s - num) >= 0 { + include_val = x.at(i - 1).at(s - num) + } + + if exclude != none and include_val != none { + exclude or include_val + } else { + none + } + } + } + } + + let F = ((nums)) => map_tensor(F_i((nums)), dim: 2); // <--- ADDED SEMICOLON + + let pi = ((nums, target)) => (x) => { + x.at(n).at(target) + } + + // Visualization helper + let x_h(x, diff_mask: none) = { + set text(weight: "bold") + let rows = () + + // Header row + let header_cells = () + header_cells.push(rect(fill: green.transparentize(70%), inset: 4pt)[$i$]) + header_cells.push(rect(fill: green.transparentize(70%), inset: 4pt)[$"num"$]) + + for s in range(0, target + 1) { + header_cells.push(rect(fill: orange.transparentize(70%), inset: 4pt)[$#s$]) + } + rows.push(grid(columns: header_cells.len() * (14pt,), rows: 14pt, align: center + horizon, ..header_cells)) + + // Data rows + for i in range(0, n + 1) { + let row = () + + // Row label + if i == 0 { + row.push(rect(fill: green.transparentize(70%), inset: 4pt)[$0$]) + row.push(rect(fill: green.transparentize(70%), inset: 4pt)[$emptyset$]) + } else { + row.push(rect(fill: green.transparentize(70%), inset: 4pt)[$#i$]) + row.push(rect(fill: green.transparentize(70%), inset: 4pt)[$#nums.at(i - 1)$]) + } + + // DP values + for s in range(0, target + 1) { + let val = x.at(i).at(s) + let display_val = if val == none { + text(fill: purple)[$bot$] + } else if val == true { + text(fill: green.darken(20%))[T] + } else { + text(fill: red.darken(20%))[F] + } + + let fill_color = if diff_mask != none and diff_mask.at(i).at(s) { + yellow.transparentize(70%) + } else { + white + } + + row.push(rect(stroke: gray, fill: fill_color, inset: 4pt)[$#display_val$]) + } + + rows.push(grid(columns: row.len() * (14pt,), rows: 14pt, align: center + horizon, ..row)) + } + + grid(align: center, ..rows) + } + + mapcode-viz( + rho, F((nums)), pi((nums, target)), + X_h: x_h, + F_name: [$F_("nums")$], + pi_name: [$pi_("nums")$], + group-size: calc.min(3, n + 1), + cell-size: 60mm, scale-fig: 75% + )((nums, target)) + } else { + [Cannot partition: total sum is odd.] + } +} +$ +) + +*Result:* The final value at $"dp"[#n][#inst_target]$ is `true`, meaning the array $#inst_nums$ can be partitioned into two equal-sum subsets: [1, 2, 2] and [5]. \ No newline at end of file diff --git a/algorithms/fibonacci.typ b/algorithms/fibonacci.typ index 8dbb29d..4ecf268 100644 --- a/algorithms/fibonacci.typ +++ b/algorithms/fibonacci.typ @@ -71,7 +71,7 @@ $ mapcode-viz( rho,F, pi(inst), - X_h: X_h, + // X_h: X_h, pi_name: [$mpi (inst)$], group-size: calc.min(6, inst), cell-size: 10mm, scale-fig: 95% From a324b228caf2f98c39027c7b41fa9d2d2d8d65b8 Mon Sep 17 00:00:00 2001 From: miryala10sathvika Date: Sun, 16 Nov 2025 19:36:40 +0530 Subject: [PATCH 3/3] adding to main --- main.typ | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/main.typ b/main.typ index 9952d9b..a243119 100644 --- a/main.typ +++ b/main.typ @@ -52,3 +52,8 @@ 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/decode_ways.typ" +#pagebreak() +#include "algorithms/equal_sum_subset.typ" +#pagebreak() \ No newline at end of file