Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New challenge: FSA #15

Merged
merged 39 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
c3c71a2
New challenge: FSA
dcodesdev Jun 5, 2024
0d994f3
tests update
dcodesdev Jun 6, 2024
54344dc
FSA description update
dcodesdev Jun 6, 2024
c73c934
maze solver
dcodesdev Jun 6, 2024
f940865
tests update
dcodesdev Jun 6, 2024
d734744
tests fix
dcodesdev Jun 6, 2024
74d91b6
readme renamed
dcodesdev Jun 6, 2024
2c06aa5
syntest
dcodesdev Jun 6, 2024
b750a52
Feature/syntest #16 from dcodesdev/feature/syntest
dcodesdev Jun 6, 2024
4c6e49d
syntest from &str
dcodesdev Jun 6, 2024
f4361ee
new challenge variable declaration
dcodesdev Jun 6, 2024
8e60327
declaring vars tests
dcodesdev Jun 6, 2024
88794a0
syntest update
dcodesdev Jun 7, 2024
16487fc
fix
dcodesdev Jun 7, 2024
f47acaf
syntest find variables
dcodesdev Jun 7, 2024
616ab26
handles return keyword
dcodesdev Jun 7, 2024
f32821b
handles panics
dcodesdev Jun 7, 2024
6403713
var exists helper
dcodesdev Jun 7, 2024
ee0fd08
syntest var details
dcodesdev Jun 7, 2024
b65bf64
syntest local var impl
dcodesdev Jun 7, 2024
f6a764c
declaring vars test
dcodesdev Jun 7, 2024
604f7ff
install syn
dcodesdev Jun 7, 2024
de8da4a
description update
dcodesdev Jun 7, 2024
2428377
syntest variable name display
dcodesdev Jun 7, 2024
2769946
var.rs
dcodesdev Jun 7, 2024
93e43f9
var details fix
dcodesdev Jun 7, 2024
4a7a1a7
syntest value
dcodesdev Jun 7, 2024
e01c1e4
declaring vars test
dcodesdev Jun 7, 2024
d7e6fed
test only mod
dcodesdev Jun 7, 2024
e4436a7
readme
dcodesdev Jun 7, 2024
a8a5adf
new test
dcodesdev Jun 7, 2024
1a11cd9
matching nested binaries
dcodesdev Jun 7, 2024
673102b
declare variables challenge review
dcodesdev Jun 7, 2024
4426386
FSA
dcodesdev Jun 7, 2024
1c86422
maze solver desc update
dcodesdev Jun 7, 2024
e0f9879
multi solution test
dcodesdev Jun 7, 2024
b0e293c
date update
dcodesdev Jun 7, 2024
e5dee89
challenges test file update
dcodesdev Jun 7, 2024
6d555f0
tempfile dep removed
dcodesdev Jun 7, 2024
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
32 changes: 28 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

File renamed without changes.
3 changes: 2 additions & 1 deletion challenges/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ serde = { version = "1.0.200", features = ["derive"] }
serde_json = "1.0.116"
toml = "0.8.12"

[lib]
[[test]]
name = "tests"
path = "tests.rs"
36 changes: 36 additions & 0 deletions challenges/challenges.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@
"created_at": "2024-04-20T00:00:00Z",
"updated_at": "2024-04-20T00:00:00Z"
},
{
"id": 22,
"title": "Declaring Variables",
"slug": "declaring-variables",
"short_description": "Learn to declare immutable variables in Rust and understand their usage.",
"language": "RUST",
"difficulty": "BEGINNER",
"track": "RUST_BASICS",
"tags": ["variables", "immutability"],
"created_at": "2024-06-07T00:00:00Z",
"updated_at": "2024-06-07T00:00:00Z"
},
{
"id": 2,
"title": "Character counting string",
Expand Down Expand Up @@ -231,5 +243,29 @@
"tags": ["control flow", "palindrome"],
"created_at": "2024-06-05T00:00:00Z",
"updated_at": "2024-06-05T00:00:00Z"
},
{
"id": 20,
"title": "Finite State Automaton",
"slug": "finite-state-automaton",
"short_description": "Implement a finite state automaton (FSA) to recognize a specific pattern in a sequence of characters.",
"language": "RUST",
"difficulty": "HARD",
"track": "CONTROL_FLOW",
"tags": ["pattern recognition", "automata theory", "control flow"],
"created_at": "2024-06-07T00:00:00Z",
"updated_at": "2024-06-07T00:00:00Z"
},
{
"id": 21,
"title": "Maze Solver",
"slug": "maze-solver",
"short_description": "Implement a maze solver using control flow in Rust to navigate through a maze represented as a grid.",
"language": "RUST",
"difficulty": "ADVANCED",
"track": "CONTROL_FLOW",
"tags": ["control flow", "algorithms", "path-finding"],
"created_at": "2024-06-07T00:00:00Z",
"updated_at": "2024-06-07T00:00:00Z"
}
]
10 changes: 10 additions & 0 deletions challenges/declaring-variables/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "declaring-variables"
version = "0.1.0"
edition = "2021"

[dependencies]

[dev-dependencies]
syntest = { path = "../../crates/syntest" }
syn = "2.0.66"
30 changes: 30 additions & 0 deletions challenges/declaring-variables/description.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
## Declaring variables challenge

Declaring variables in programming is a fundamental concept that allows you to **store and manipulate data**. Variables are used to store values that can be accessed and modified throughout the program.

In Rust, variables are declared using the `let` keyword followed by the variable name and an optional type annotation.

In Rust, variables are **immutable by default**. This means that once a value is bound to a variable, it cannot be changed. This is a key feature of Rust that helps ensure safety and prevent bugs by avoiding unexpected changes to values.

## Your task

In this challenge, you will declare and use immutable variables in Rust. You will be given a function where you need to **declare variables** and use them to perform specific operations. The goal is to get comfortable with the concept of **immutability and understand how to use immutable variables effectively.**

Your task is to define two immutable variables inside the function using the `let` keyword:

- `width` with a value of `10`
- `height` with a value of `5`

Then, calculate the area of a rectangle using the formula `area = width * height` and return the calculated area.

## Requirements

- Declare two immutable variables, `width` and `height`, and assign them values.
- Calculate the area of the rectangle using the formula `width * height`.
- Return the calculated area.

## Hints

- Use the `let` keyword to declare variables.
- Remember that variables declared with `let` are immutable by default.
- Use multiplication `*` to calculate the area.
6 changes: 6 additions & 0 deletions challenges/declaring-variables/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pub fn calculate_area() -> u32 {
let width = 10;
let height = 5;

width * height
}
6 changes: 6 additions & 0 deletions challenges/declaring-variables/src/starter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pub fn calculate_area() -> u32 {
// TODO: Implement the function here
// Declare width and height as immutable variables
// Calculate the area of the rectangle
// Return the calculated area
}
32 changes: 32 additions & 0 deletions challenges/declaring-variables/tests/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#[cfg(test)]
mod tests {
use declaring_variables::*;
use syntest::{Syntest, Value};

#[test]
fn test_calculate_area() {
assert_eq!(calculate_area(), 50);
}

#[test]
fn test_variables() {
let syntest = Syntest::from("./src/lib.rs");

// Expect the 2 variables to exist
let variables_to_exist = ["height", "width"];
variables_to_exist.iter().for_each(|&v| {
let var = syntest
.var_details("calculate_area", v)
.expect(&format!("Variable {} was not declared", v));

assert!(var.is_used(), "Variable {v} was not used");
assert_eq!(var.name(), v);

if v == "width" {
assert_eq!(var.value(), Value::Int(10), "Width should be 10");
} else if v == "height" {
assert_eq!(var.value(), Value::Int(5), "Height should be 5");
}
});
}
}
6 changes: 6 additions & 0 deletions challenges/finite-state-automaton/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "finite-state-automaton"
version = "0.1.0"
edition = "2021"

[dependencies]
48 changes: 48 additions & 0 deletions challenges/finite-state-automaton/description.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
In this challenge, you will implement a **finite state automaton (FSA)** to recognize a specific pattern in a sequence of characters.

## What is a Finite State Automaton?

A finite state automaton is a mathematical model of computation used to design both computer programs and sequential logic circuits. It is a powerful tool for **pattern matching as it consists of a finite number of states and transitions between these states based on input symbols**.

Finite state automatons are widely used in **text processing, lexical analysis**, and many other areas where **pattern recognition** is essential.

## Your Task

You need to create an FSA that can recognize the pattern **"ab\*c"**, where:

- **'a'** is followed by zero or more **'b'**s and then followed by **'c'**.

You will implement a function `recognize_pattern` that takes a string slice as input and returns a boolean indicating whether the input string matches the pattern.

## Requirements

- Implement the finite state automaton using Rust's **enums** and the `match` statement.
- The function should handle **empty strings** and any invalid input gracefully.
- Your **FSA** should consist of states and transitions implemented as Rust enums and functions.
- You must handle state transitions explicitly using the `match` statement.

## Example

```rust
let result = recognize_pattern("abbbc");
assert_eq!(result, true);

let result = recognize_pattern("ac");
assert_eq!(result, true);

let result = recognize_pattern("abbbd");
assert_eq!(result, false);

let result = recognize_pattern("");
assert_eq!(result, false);
```

> Did You Know?
>
> **Finite state automatons** have a wide range of applications outside computer science as well. For example, they are used in the design of digital circuits. In digital circuit design, an FSA can be used to create sequential circuits such as counters and communication protocol controllers. FSAs are also used in the field of linguistics to model the morphology of languages and in robotics to control the behavior of autonomous robots.

## Hints

- Think about how you can represent states and transitions using Rust enums.
- Carefully plan the transitions between states based on the input characters.
- Make sure to handle edge cases, such as an empty input string or invalid characters.
29 changes: 29 additions & 0 deletions challenges/finite-state-automaton/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#[derive(Debug)]
enum State {
Start,
A,
B,
C,
Invalid,
}

pub fn recognize_pattern(input: &str) -> bool {
let mut state = State::Start;

for ch in input.chars() {
state = match (state, ch) {
(State::Start, 'a') => State::A,
(State::A, 'b') => State::B,
(State::A, 'c') => State::C,
(State::B, 'b') => State::B,
(State::B, 'c') => State::C,
_ => State::Invalid,
};

if let State::Invalid = state {
return false;
}
}

matches!(state, State::C)
}
5 changes: 5 additions & 0 deletions challenges/finite-state-automaton/src/starter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub fn recognize_pattern(input: &str) -> bool {
// Implement your finite state automaton here

false
}
49 changes: 49 additions & 0 deletions challenges/finite-state-automaton/tests/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#[cfg(test)]
mod tests {
use finite_state_automaton::*;

#[test]
fn test_recognize_pattern_valid() {
assert_eq!(recognize_pattern("abbbc"), true);
assert_eq!(recognize_pattern("ac"), true);
assert_eq!(recognize_pattern("ab"), false);
assert_eq!(recognize_pattern("abbc"), true);
assert_eq!(recognize_pattern("abbbbbc"), true);
}

#[test]
fn test_recognize_pattern_invalid() {
assert_eq!(recognize_pattern("abbbd"), false);
assert_eq!(recognize_pattern(""), false);
assert_eq!(recognize_pattern("a"), false);
assert_eq!(recognize_pattern("abbd"), false);
assert_eq!(recognize_pattern("abbbcc"), false);
}

#[test]
fn test_recognize_pattern_edge_cases() {
assert_eq!(recognize_pattern("abbbbbc"), true);
assert_eq!(recognize_pattern("a"), false);
assert_eq!(recognize_pattern("abc"), true);
assert_eq!(recognize_pattern("abbc"), true);
assert_eq!(recognize_pattern("ab"), false);
}

#[test]
fn test_recognize_pattern_long_input() {
let long_input_valid = "a".to_owned() + "b".repeat(434).as_str() + "c";
let long_input_invalid = "a".to_owned() + "b".repeat(333).as_str() + "d";
assert_eq!(recognize_pattern(&long_input_valid), true);
assert_eq!(recognize_pattern(&long_input_invalid), false);
assert_eq!(recognize_pattern(&(long_input_valid.clone() + "c")), false);
}

#[test]
fn test_recognize_pattern_random_cases() {
assert_eq!(recognize_pattern("abbbbbbbbbc"), true);
assert_eq!(recognize_pattern("abbbbbbbbd"), false);
assert_eq!(recognize_pattern("aabbcc"), false);
assert_eq!(recognize_pattern("abbbc"), true);
assert_eq!(recognize_pattern("acc"), false);
}
}
6 changes: 6 additions & 0 deletions challenges/maze-solver/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "maze-solver"
version = "0.1.0"
edition = "2021"

[dependencies]
Loading
Loading