Skip to content

Commit

Permalink
Merge pull request #1 from SKTT1Ryze/add_two_numbers
Browse files Browse the repository at this point in the history
Add two numbers
  • Loading branch information
SKTT1Ryze authored Oct 11, 2023
2 parents 8dc4816 + b01f612 commit c36d399
Show file tree
Hide file tree
Showing 10 changed files with 238 additions and 6 deletions.
1 change: 1 addition & 0 deletions leetcode/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//! Collections of problems and solutions in LeetCode

mod list;
pub mod problems;
pub mod solutions;
95 changes: 95 additions & 0 deletions leetcode/src/list.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Definition for singly-linked list.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode<T: PartialEq + Eq> {
pub val: T,
pub next: Option<Box<ListNode<T>>>,
}

impl<T: PartialEq + Eq> ListNode<T> {
#[inline]
pub fn new(val: T) -> Self {
ListNode { next: None, val }
}

pub fn create_list<const N: usize>(v: [T; N]) -> Option<Box<Self>> {
let mut head = None;

for item in v.into_iter().rev() {
head = Some(Box::new(ListNode {
val: item,
next: head,
}));
}

head
}
}

pub fn assert_eq_list<T: PartialEq + Eq>(
l1: &Option<Box<ListNode<T>>>,
l2: &Option<Box<ListNode<T>>>,
) -> bool {
let mut p1 = l1;
let mut p2 = l2;
while let (Some(node1), Some(node2)) = (p1, p2) {
if node1.val != node2.val {
return false;
}
p1 = &node1.next;
p2 = &node2.next;
}

p1.is_none() && p2.is_none()
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_create_list() {
let v = [1, 3, 2];
let list = ListNode::create_list(v);

let mut head = &list;
let mut v = Vec::from(v);
while let Some(node) = head {
let item = v.remove(0);
assert_eq!(item, node.val);
head = &node.next;
}
}

#[test]
fn test_assert_eq_list() {
let l1 = Some(Box::new(ListNode {
val: 0,
next: Some(Box::new(ListNode {
val: 1,
next: Some(Box::new(ListNode { val: 2, next: None })),
})),
}));
let l2 = Some(Box::new(ListNode {
val: 0,
next: Some(Box::new(ListNode {
val: 1,
next: Some(Box::new(ListNode { val: 2, next: None })),
})),
}));
let l3 = Some(Box::new(ListNode {
val: 0,
next: Some(Box::new(ListNode {
val: 1,
next: Some(Box::new(ListNode { val: 3, next: None })),
})),
}));
let l4 = Some(Box::new(ListNode {
val: 0,
next: Some(Box::new(ListNode { val: 1, next: None })),
}));

assert!(assert_eq_list(&l1, &l2));
assert!(!assert_eq_list(&l1, &l3));
assert!(!assert_eq_list(&l1, &l4));
}
}
1 change: 1 addition & 0 deletions leetcode/src/problems.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod add_two_numbers;
pub mod two_sum;

#[allow(dead_code)]
Expand Down
28 changes: 28 additions & 0 deletions leetcode/src/problems/add_two_numbers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use super::{Difficulty, Problem, Topic};

pub struct AddTwoNumbers;

impl Problem for AddTwoNumbers {
fn id(&self) -> usize {
2
}
fn difficulty(&self) -> Difficulty {
Difficulty::Medium
}
fn topic(&self) -> Topic {
Topic::Algorithms
}
fn title(&self) -> String {
"Add Two Numbers".into()
}
fn description(&self) -> String {
r#"You are given two non-empty linked lists representing two non-negative integers.
The digits are stored in reverse order, and each of their nodes contains a single digit.
Add the two numbers and return the sum as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself."#
.into()
}
fn labels(&self) -> Vec<String> {
["link list".into()].into()
}
}
1 change: 1 addition & 0 deletions leetcode/src/solutions.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use anyhow::Result;

pub mod add_two_numbers;
pub mod two_sum;

pub trait Solution: Send + Sync {
Expand Down
93 changes: 93 additions & 0 deletions leetcode/src/solutions/add_two_numbers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use super::Solution;
use crate::list::{assert_eq_list, ListNode};

pub struct AddTwoNumbers;

impl Solution for AddTwoNumbers {
fn name(&self) -> String {
"Add Two Numbers Solution".into()
}
fn problem_id(&self) -> usize {
2
}
fn test(&self) -> anyhow::Result<()> {
let testcases = [
(
ListNode::create_list([2, 4, 3]),
ListNode::create_list([5, 6, 4]),
ListNode::create_list([7, 0, 8]),
),
(
ListNode::create_list([0]),
ListNode::create_list([0]),
ListNode::create_list([0]),
),
(
ListNode::create_list([9, 9, 9, 9, 9, 9, 9]),
ListNode::create_list([9, 9, 9, 9]),
ListNode::create_list([8, 9, 9, 9, 0, 0, 0, 1]),
),
];

for (l1, l2, expect) in testcases {
let output = Self::add_two_numbers(l1, l2);

if !assert_eq_list(&expect, &output) {
// TODO: print link list
anyhow::bail!("test failed in AddTwoNumbers solution");
}
}
Ok(())
}
fn benchmark(&self) -> anyhow::Result<usize> {
anyhow::bail!("TODO");
}
}

impl AddTwoNumbers {
pub fn add_two_numbers(
mut l1: Option<Box<ListNode<i32>>>,
mut l2: Option<Box<ListNode<i32>>>,
) -> Option<Box<ListNode<i32>>> {
let mut head = None;
let mut p = &mut head;
let mut residue = 0;

while let (Some(node1), Some(node2)) = (l1.as_ref(), l2.as_ref()) {
let val = (node1.val + node2.val + residue) % 10;
residue = (node1.val + node2.val + residue) / 10;

*p = Some(Box::new(ListNode::new(val)));
p = &mut p.as_mut().unwrap().next;

l1 = l1.take().unwrap().next;
l2 = l2.take().unwrap().next;
}

while let Some(node) = l1.take() {
let val = (node.val + residue) % 10;
residue = (node.val + residue) / 10;

*p = Some(Box::new(ListNode::new(val)));
p = &mut p.as_mut().unwrap().next;

l1 = node.next;
}

while let Some(node) = l2.take() {
let val = (node.val + residue) % 10;
residue = (node.val + residue) / 10;

*p = Some(Box::new(ListNode::new(val)));
p = &mut p.as_mut().unwrap().next;

l2 = node.next;
}

if residue > 0 {
*p = Some(Box::new(ListNode::new(residue)));
}

head
}
}
1 change: 1 addition & 0 deletions runtime/rust-toolchain
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nightly
9 changes: 9 additions & 0 deletions runtime/rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error_on_line_overflow = false
format_strings = true
normalize_comments = true
imports_granularity = "Crate"
reorder_modules = true
# enum_discrim_align_threshold = 20
use_try_shorthand = true
wrap_comments = true
edition = "2021"
9 changes: 5 additions & 4 deletions runtime/src/container.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::{
collections::HashMap,
sync::{Arc, Mutex},
};

use leetcode::problems::Problem;
use leetcode::solutions::Solution;
use leetcode::{problems::Problem, solutions::Solution};

#[derive(Default)]
pub struct Container {
Expand Down
6 changes: 4 additions & 2 deletions runtime/src/registration.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use super::container::ContainerHandle;

use leetcode::problems;
use leetcode::solutions;
use leetcode::{problems, solutions};

pub fn register_all(handle: ContainerHandle) -> anyhow::Result<()> {
handle.register_problem(|_| problems::two_sum::TwoSum)?;
handle.register_solution(|_| solutions::two_sum::TwoSum)?;

handle.register_problem(|_| problems::add_two_numbers::AddTwoNumbers)?;
handle.register_solution(|_| solutions::add_two_numbers::AddTwoNumbers)?;

Ok(())
}

0 comments on commit c36d399

Please sign in to comment.