Skip to content

Instantly share code, notes, and snippets.

@laggycomputer
Created September 5, 2025 03:25
Show Gist options
  • Select an option

  • Save laggycomputer/499424160ac68e82ac435f83f0274f65 to your computer and use it in GitHub Desktop.

Select an option

Save laggycomputer/499424160ac68e82ac435f83f0274f65 to your computer and use it in GitHub Desktop.
rust valid change
use std::ops::{Add, Sub};
use num_traits::CheckedSub;
#[derive(Default, Copy, Clone, Debug)]
struct Coins {
pub penny: u64,
pub nickel: u64,
pub dime: u64,
pub quarter: u64,
}
impl Sub for Coins {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Self {
penny: self.penny - rhs.penny,
nickel: self.nickel - rhs.nickel,
dime: self.dime - rhs.dime,
quarter: self.quarter - rhs.quarter,
}
}
}
impl num_traits::CheckedSub for Coins {
fn checked_sub(&self, v: &Self) -> Option<Self> {
Some(Self {
penny: self.penny.checked_sub(v.penny)?,
nickel: self.nickel.checked_sub(v.nickel)?,
dime: self.dime.checked_sub(v.dime)?,
quarter: self.quarter.checked_sub(v.quarter)?,
})
}
}
impl Add for Coins {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self {
penny: self.penny + rhs.penny,
nickel: self.nickel + rhs.nickel,
dime: self.dime + rhs.dime,
quarter: self.quarter + rhs.quarter,
}
}
}
impl Coins {
fn penny() -> Self {
Self {
penny: 1,
..Default::default()
}
}
fn nickel() -> Self {
Self {
nickel: 1,
..Default::default()
}
}
fn dime() -> Self {
Self {
dime: 1,
..Default::default()
}
}
fn quarter() -> Self {
Self {
quarter: 1,
..Default::default()
}
}
fn value(&self) -> u64 {
self.penny * 1 + self.nickel * 5 + self.dime * 10 + self.quarter * 25
}
fn try_change_for(self, running: Coins, amount: u64) -> Option<Self> {
let one_penny = Self::penny();
let one_nickel = Self::nickel();
let one_dime = Self::dime();
let one_quarter = Self::quarter();
amount
.checked_sub(one_quarter.value())
.and_then(|sub| {
self.checked_sub(&one_quarter)?
.try_change_for(running + one_quarter, sub)
})
.or_else(|| {
amount.checked_sub(one_dime.value()).and_then(|sub| {
self.checked_sub(&one_dime)?
.try_change_for(running + one_dime, sub)
})
})
.or_else(|| {
amount.checked_sub(one_nickel.value()).and_then(|sub| {
self.checked_sub(&one_nickel)?
.try_change_for(running + one_nickel, sub)
})
})
.or_else(|| {
amount.checked_sub(one_penny.value()).and_then(|sub| {
self.checked_sub(&one_penny)?
.try_change_for(running + one_penny, sub)
})
})
.or_else(|| (amount == 0).then_some(running))
}
}
fn main() {
let c = Coins {
penny: 1,
nickel: 1,
dime: 2,
quarter: 1,
};
dbg!(c.try_change_for(Coins::default(), 30));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment