From ed4bb2fc5dc93f1227da1968867ed3fe1047737220df6cdca844c4b87c0152fb Mon Sep 17 00:00:00 2001 From: Mars Ultor Date: Fri, 18 Apr 2025 13:33:19 -0500 Subject: [PATCH] i love procrastinating --- .gitignore | 1 + Cargo.lock | 7 +++++ README.md | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/main.rs | 50 +++++++++++++++++++++++++++++++++++- 4 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 Cargo.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a2ddd8a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target/** diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..0d7f232 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "minimizing-coins" +version = "0.1.0" diff --git a/README.md b/README.md index cd30349..41864b0 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,75 @@ # minimizing-coins -Some demo of Rust for Comp Sci Club \ No newline at end of file +## Problem +### Minimum Number of Coins + +Consider a money system consisting of `n` coins. Each coin has a positive integer value. Your task is to produce a sum of money `x` using the available coins in such a way that the number of coins is minimized. + +For example, if the coins are `{1, 5, 7}` and the desired sum is `11`, an optimal solution is `5 + 5 + 1`, which requires 3 coins. + +--- + +### Input + +The first input line has two integers `n` and `x`: +- `n` — the number of coins +- `x` — the desired sum of money + +The second line has `n` distinct integers `c₁, c₂, ..., cₙ`: the value of each coin. + +--- + +### Output + +Print one integer: the **minimum** number of coins needed to produce the sum `x`. +If it is **not possible**, print `-1`. + +--- + +### Constraints + +- `1 ≤ n ≤ 100` +- `1 ≤ x ≤ 10⁶` +- `1 ≤ cᵢ ≤ 10⁶` + +## Core logic + +```rust +fn find_min(cache: &mut HashMap, target_sum: u64, coins: &Vec) -> Option { + if let Some(&entry) = cache.get(&target_sum) { + return Some(entry); + } + + let mut running_min: u64 = u64::MAX; + + for &coin in coins { + if coin > target_sum { + continue; + } + + let new_target = target_sum - coin; + + if new_target == 0 { + cache.insert(target_sum, 1); // cache base case + return Some(1); + } + + if let Some(path) = find_min(cache, new_target, coins) { + let num_coins = 1 + path; + if num_coins < running_min { + running_min = num_coins; + } + } + } + + if running_min != u64::MAX { + cache.insert(target_sum, running_min); + Some(running_min) + } else { + cache.insert(target_sum, u64::MAX); // Mark as unreachable + None + } +} +``` + +Essentially, the purpose of the above code is to traverse a tree of possible coin decisions. As long as the coin denomination is smaller than the target, it's possible to recursively iterate through all combinations of coins while both caching and checking for a base case. This behavior is called memorization. The base case for any branch of the tree is when the target sum is equivalent to the coin of interest. diff --git a/src/main.rs b/src/main.rs index cb512be..3a3512c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,51 @@ +use std::{collections::HashMap}; + fn main() { - println!("Hello, world!"); + let mut line_buf: String = String::new(); + std::io::stdin().read_line(&mut line_buf); + let first_line: Vec = line_buf.split_whitespace().into_iter().map(|item| item.parse::().unwrap()).collect(); + line_buf=String::new(); + std::io::stdin().read_line(&mut line_buf); + let second_line: Vec = line_buf.split_whitespace().into_iter().map(|item| item.parse::().unwrap()).collect(); + //println!("Coins: {:#?}", second_line); + println!("{:#?}", find_min(&mut HashMap::new(), *first_line.get(1).unwrap(), &second_line)); } + + + +fn find_min(cache: &mut HashMap, target_sum: u64, coins: &Vec) -> Option { + if let Some(&entry) = cache.get(&target_sum) { + return Some(entry); + } + + let mut running_min: u64 = u64::MAX; + + for &coin in coins { + if coin > target_sum { + continue; + } + + let new_target = target_sum - coin; + + if new_target == 0 { + cache.insert(target_sum, 1); // cache base case + return Some(1); + } + + if let Some(path) = find_min(cache, new_target, coins) { + let num_coins = 1 + path; + if num_coins < running_min { + running_min = num_coins; + } + } + } + + if running_min != u64::MAX { + cache.insert(target_sum, running_min); + Some(running_min) + } else { + cache.insert(target_sum, u64::MAX); // Mark as unreachable + None + } +} +