diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index e2611ed..ab46dcf 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -2,95 +2,99 @@ name: Rust -> Build & Test & Release on: push: - branches: ["main"] + branches: [ "main" ] env: CARGO_TERM_COLOR: always - PROJECT_NAME: ${{ github.event.repository.name }} jobs: build_linux: + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - name: Build - run: cargo build --release --verbose - - name: Run tests - run: cargo test --verbose + - uses: actions/checkout@v4 + - name: Build + run: cargo build --release --verbose + - name: Run tests + run: cargo test --verbose - - name: Upload Linux Binary - uses: actions/upload-artifact@v4 - with: - name: ${{ env.PROJECT_NAME }}-linux-x64_86 - path: target/release/${{ env.PROJECT_NAME }} + - name: Upload Linux Binary + uses: actions/upload-artifact@v4 + with: + name: banker_algorithm_linux_x64_86 + path: target/release/banker-algorithm build_windows: + runs-on: windows-latest steps: - - uses: actions/checkout@v4 - - name: Build - run: cargo build --release --verbose - - name: Run tests - run: cargo test --verbose + - uses: actions/checkout@v4 + - name: Build + run: cargo build --release --verbose + - name: Run tests + run: cargo test --verbose - - name: Upload Windows Binary - uses: actions/upload-artifact@v4 - with: - name: ${{ env.PROJECT_NAME }}-windows-x64_86 - path: target/release/${{ env.PROJECT_NAME }}.exe + - name: Upload Windows Binary + uses: actions/upload-artifact@v4 + with: + name: banker_algorithm_windows_x64_86 + path: target/release/banker-algorithm.exe build_macos: + runs-on: macos-latest steps: - - uses: actions/checkout@v4 - - name: Build - run: cargo build --release --verbose - - name: Run tests - run: cargo test --verbose + - uses: actions/checkout@v4 + - name: Build + run: cargo build --release --verbose + - name: Run tests + run: cargo test --verbose - - name: Upload MacOS Binary - uses: actions/upload-artifact@v4 - with: - name: ${{ env.PROJECT_NAME }}-macos-arm64 - path: target/release/${{ env.PROJECT_NAME }} + - name: Upload MacOS Binary + uses: actions/upload-artifact@v4 + with: + name: banker_algorithm_macos_x64_86 + path: target/release/banker-algorithm release: needs: [build_linux, build_windows, build_macos] runs-on: ubuntu-latest - permissions: - contents: write + permissions: + contents: write steps: - - uses: actions/checkout@v4 - - name: Forge a Folder - run: mkdir Downloads - working-directory: /home/runner/work/${{ env.PROJECT_NAME }}/${{ env.PROJECT_NAME }}/ - - uses: actions/download-artifact@v4 - name: Download - with: - path: Downloads/ + - uses: actions/checkout@v4 + - name: Forge a Folder + run: mkdir Downloads + working-directory: /home/runner/work/banker-algorithm/banker-algorithm/ - - name: Rename Binaries - run: | - tree Downloads/ - mv Downloads/${{ env.PROJECT_NAME }}-linux-x64_86/${{ env.PROJECT_NAME }} Downloads/${{ env.PROJECT_NAME }}-linux-x64_86/${{ env.PROJECT_NAME }}-linux-x64_86 - mv Downloads/${{ env.PROJECT_NAME }}-windows-x64_86/${{ env.PROJECT_NAME }}.exe Downloads/${{ env.PROJECT_NAME }}-windows-x64_86/${{ env.PROJECT_NAME }}-windows-x64_86.exe - mv Downloads/${{ env.PROJECT_NAME }}-macos-arm64/${{ env.PROJECT_NAME }} Downloads/${{ env.PROJECT_NAME }}-macos-arm64/${{ env.PROJECT_NAME }}-macos-arm64 - - name: Git Commit SHA - id: vars - run: | - calculatedSha=$(git rev-parse --short ${{ github.sha }}) - echo "short_sha=$calculatedSha" >> $GITHUB_OUTPUT + - uses: actions/download-artifact@v4 + name: Download + with: + path: Downloads/ + + - name: Rename Binaries + run: | + mv Downloads/banker_algorithm_linux_x64_86/banker-algorithm Downloads/banker_algorithm_linux_x64_86/banker-algorithm-linux_x64_86 + mv Downloads/banker_algorithm_windows_x64_86/banker-algorithm.exe Downloads/banker_algorithm_windows_x64_86/banker-algorithm-windows_x64_86.exe + mv Downloads/banker_algorithm_macos_x64_86/banker-algorithm Downloads/banker_algorithm_macos_x64_86/banker-algorithm-macos_x64_86 - - uses: softprops/action-gh-release@v2 - name: Release - with: - tag_name: ${{ steps.vars.outputs.short_sha }} - generate_release_notes: true - files: | - Downloads/*linux*/${{ env.PROJECT_NAME }}* - Downloads/*windows*/${{ env.PROJECT_NAME }}* - Downloads/*macos*/${{ env.PROJECT_NAME }}* + - name: Git Commit SHA + id: vars + run: | + calculatedSha=$(git rev-parse --short ${{ github.sha }}) + echo "short_sha=$calculatedSha" >> $GITHUB_OUTPUT + + - uses: softprops/action-gh-release@v2 + name: Release + with: + tag_name: ${{ steps.vars.outputs.short_sha }} + generate_release_notes: true + files: | + Downloads/*linux*/*banker* + Downloads/*windows*/*banker* + Downloads/*macos*/*banker* + \ No newline at end of file diff --git a/README.md b/README.md index d1bf91b..8da1973 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,12 @@ >When you run the program, it will ask you to give resource capacity for A, B and C. - +![Screenshot_20240115_012732](https://github.com/Tahinli/banker-algorithm/assets/96421894/9cdfc5c3-0622-4e5a-9ac6-afd083947cc3) >Program will create solvable matrixses and waits for you to give process queue correctly then checks your result. - +![Screenshot_20240115_012746](https://github.com/Tahinli/banker-algorithm/assets/96421894/4d7a5cd5-a99e-4354-a644-caa778e0a89e) >At the end you can check your answers. diff --git a/assets/interaction.png b/assets/interaction.png deleted file mode 100644 index 06cb8e7..0000000 Binary files a/assets/interaction.png and /dev/null differ diff --git a/assets/matrix.png b/assets/matrix.png deleted file mode 100644 index b71ff6e..0000000 Binary files a/assets/matrix.png and /dev/null differ diff --git a/src/main.rs b/src/main.rs index d59c275..4f28f4c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,280 +1,357 @@ -use rand::Rng; use std::io; +use rand::Rng; -const PROCESS_COUNT: usize = 5; -const RESOURCE_COUNT: usize = 3; - +const PROCESS_COUNT:usize = 5; +const RESOURCE_COUNT:usize = 3; fn main() { println!("Hello, world!"); - let mut restart: bool = true; - while restart { - println!("Max A Resource"); - let a = match get_u8_input() { - Some(resource_input) => resource_input, - None => return, - }; - - println!("Max B Resource"); - let b = match get_u8_input() { - Some(resource_input) => resource_input, - None => return, - }; - - println!("Max C Resource"); - let c = match get_u8_input() { - Some(resource_input) => resource_input, - None => return, - }; - - println!("\n\tA = {}\n\tB = {}\n\tC = {}", a, b, c); - if a == 0 || b == 0 || c == 0 { - eprintln!("Exit: Zero as a Input is Invalid"); - return; - } - - let mut max_needs_matrix = [[0_u8; RESOURCE_COUNT]; PROCESS_COUNT]; - let mut assigned_resources_matrix = [[0_u8; RESOURCE_COUNT]; PROCESS_COUNT]; - let mut info: (bool, Vec) = (false, Vec::with_capacity(PROCESS_COUNT)); - while !info.0 { - assign_resource_matrix( - &mut max_needs_matrix, - &mut assigned_resources_matrix, - a, - b, - c, - ); - info = banker(a, b, c, max_needs_matrix, assigned_resources_matrix); - } - println!("Max Needs Matrix"); - print_matrix(max_needs_matrix); - println!("Assigned Resources Matrix"); - print_matrix(assigned_resources_matrix); - let mut answers: [u8; PROCESS_COUNT] = [0; PROCESS_COUNT]; - for (answer, correct_answer) in answers.iter_mut().zip(&info.1) { - println!("Which Process Should be Done Now ?"); - match get_u8_input() { - Some(input) => { - *answer = input; - if *correct_answer == input { - println!("Correct"); - } else { - println!("Wrong it should be = {}", correct_answer); - } + let mut restart:bool = true; + while restart + { + println!("Max A Resource"); + let a:u8; + let b:u8; + let c:u8; + let mut resource_input:String = String::new(); + if let Err(err_val) = io::stdin().read_line(&mut resource_input) + { + println!("Failed to Read: {}", err_val); + return; + } + match resource_input.trim().parse::() + { + Ok(value) => + { + a = value; + } + Err(err_val) => + { + println!("Failed to Convert: {}", err_val); + return; + } } - None => return, - } - } - println!("Your Answers"); - for answer in answers { - println!("P{}", answer); - } - println!("Correct Answers"); - for correct_answer in info.1 { - println!("P{}", correct_answer); - } - println!("Press 'r' to Restart"); - let resource_input = match get_input() { - Some(input) => input, - None => return, - }; - match resource_input.as_str() { - "r" => { - restart = true; - println!("-------------------------------"); - } - _ => { - return; - } + println!("Max B Resource"); + let mut resource_input:String = String::new(); + if let Err(err_val) = io::stdin().read_line(&mut resource_input) + { + println!("Failed to Read: {}", err_val); + return; + } + match resource_input.trim().parse::() + { + Ok(value) => + { + b = value; + } + Err(err_val) => + { + println!("Failed to Convert: {}", err_val); + return; + } + } + + println!("Max C Resource"); + let mut resource_input:String = String::new(); + if let Err(err_val) = io::stdin().read_line(&mut resource_input) + { + println!("Failed to Read: {}", err_val); + return; + } + match resource_input.trim().parse::() + { + Ok(value) => + { + c = value; + } + Err(err_val) => + { + println!("Failed to Convert: {}", err_val); + return; + } + } + + + println!("\n\tA = {}\n\tB = {}\n\tC = {}", a,b,c); + if a == 0 || b == 0 || c == 0 + { + println!("Exit: Zero as a Input Invalid"); + return; + } + + let mut max_needs_matrix = [[0_u8;RESOURCE_COUNT];PROCESS_COUNT]; + let mut assigned_resources_matrix = [[0_u8;RESOURCE_COUNT];PROCESS_COUNT]; + let mut info:(bool, Vec) = (false, Vec::with_capacity(PROCESS_COUNT)); + while !info.0 + { + for i in 0..PROCESS_COUNT + { + let mut rng = rand::thread_rng(); + let random = rng.gen_range(0..a); + max_needs_matrix[i][0] = random; + if random != 0 + { + assigned_resources_matrix[i][0] = rng.gen_range(0..random); + } + else + { + assigned_resources_matrix[i][0] = 0; + } + } + for i in 0..PROCESS_COUNT + { + let mut rng = rand::thread_rng(); + let random = rng.gen_range(0..b); + max_needs_matrix[i][1] = random; + if random != 0 + { + assigned_resources_matrix[i][1] = rng.gen_range(0..random); + } + else + { + assigned_resources_matrix[i][1] = 0; + } + } + for i in 0..PROCESS_COUNT + { + let mut rng = rand::thread_rng(); + let random = rng.gen_range(0..c); + max_needs_matrix[i][2] = random; + if random != 0 + { + assigned_resources_matrix[i][2] = rng.gen_range(0..random); + } + else + { + assigned_resources_matrix[i][2] = 0; + } + } + info = banker(a, b, c, max_needs_matrix, assigned_resources_matrix); + } + println!("Max Needs Matrix"); + print_matrix(max_needs_matrix); + println!("Assigned Resources Matrix"); + print_matrix(assigned_resources_matrix); + let mut answers:[u8;PROCESS_COUNT] = [0;PROCESS_COUNT]; + for i in 0..PROCESS_COUNT + { + println!("Which Process Should be Done Now ?"); + let mut input = String::new(); + io::stdin().read_line(&mut input).unwrap(); + let input:u8 = input.trim().parse().unwrap(); + answers[i] = input; + if info.1[i] == input + { + println!("Correct"); + } + else + { + println!("Wrong it should be = {}", info.1[i]); + } + } + println!("Your Answers"); + for i in 0..PROCESS_COUNT + { + println!("P{}", answers[i]); + } + println!("Correct Answers"); + for i in 0..PROCESS_COUNT + { + println!("P{}", info.1[i]); + } + + + let mut resource_input:String = String::new(); + println!("Press 'r' to Restart"); + if let Err(err_val) = io::stdin().read_line(&mut resource_input) + { + println!("Failed to Read: {}", err_val); + return; + } + resource_input = resource_input.trim().to_string(); + match resource_input.as_str() + { + "r" => + { + restart = true; + println!("-------------------------------"); + } + _ => + { + return; + } + } + } - } } -fn get_input() -> Option { - let mut input: String = String::new(); - if let Err(err_val) = io::stdin().read_line(&mut input) { - eprintln!("Error: Failed to Read | {}", err_val); - return None; - } - Some(input.trim_end().to_string()) -} - -fn get_u8_input() -> Option { - match get_input() { - Some(input) => match input.parse::() { - Ok(input) => Some(input), - Err(err_val) => { - eprintln!("Error: Failed to Convert | {}", err_val); - None - } - }, - None => None, - } -} - -fn assign_resource_matrix_column( - max_needs_matrix: &mut [[u8; RESOURCE_COUNT]; PROCESS_COUNT], - assigned_resources_matrix: &mut [[u8; RESOURCE_COUNT]; PROCESS_COUNT], - random_limit: u8, - which_resource: usize, -) { - for i in 0..PROCESS_COUNT { - let mut rng = rand::thread_rng(); - let random = rng.gen_range(0..random_limit); - max_needs_matrix[i][which_resource] = random; - if random != 0 { - assigned_resources_matrix[i][which_resource] = rng.gen_range(0..random); - } else { - assigned_resources_matrix[i][which_resource] = 0; - } - } -} - -fn assign_resource_matrix( - max_needs_matrix: &mut [[u8; RESOURCE_COUNT]; PROCESS_COUNT], - assigned_resources_matrix: &mut [[u8; RESOURCE_COUNT]; PROCESS_COUNT], - a: u8, - b: u8, - c: u8, -) { - assign_resource_matrix_column(max_needs_matrix, assigned_resources_matrix, a, 0); - assign_resource_matrix_column(max_needs_matrix, assigned_resources_matrix, b, 1); - assign_resource_matrix_column(max_needs_matrix, assigned_resources_matrix, c, 2); -} - -fn print_matrix(matrix: [[u8; RESOURCE_COUNT]; PROCESS_COUNT]) { - for (i, matrix_column) in matrix.iter().enumerate() { - print!("\n\t Process {}: ", i); - for matrix_value in matrix_column { - if *matrix_value > 99 { - print!(" "); - } else if *matrix_value > 9 { - print!(" "); - } else { - print!(" "); - } - print!("{}", *matrix_value); - } - println!(); - } -} - -fn banker( - a: u8, - b: u8, - c: u8, - max_needs_matrix: [[u8; RESOURCE_COUNT]; PROCESS_COUNT], - assigned_resources_matrix: [[u8; RESOURCE_COUNT]; PROCESS_COUNT], -) -> (bool, Vec) { - let mut a_remaining: u8 = 0; - let mut b_remaining: u8 = 0; - let mut c_remaining: u8 = 0; - let mut remaining_needs_matrix: [[u8; RESOURCE_COUNT]; PROCESS_COUNT] = - [[0; RESOURCE_COUNT]; PROCESS_COUNT]; - for i in 0..PROCESS_COUNT { - match a_remaining.checked_add(assigned_resources_matrix[i][0]) { - Some(result) => { - a_remaining = result; - } - None => { - return (false, vec![]); - } - } - match b_remaining.checked_add(assigned_resources_matrix[i][1]) { - Some(result) => { - b_remaining = result; - } - None => { - return (false, vec![]); - } - } - match c_remaining.checked_add(assigned_resources_matrix[i][2]) { - Some(result) => { - c_remaining = result; - } - None => { - return (false, vec![]); - } - } - remaining_needs_matrix[i][0] = max_needs_matrix[i][0] - assigned_resources_matrix[i][0]; - remaining_needs_matrix[i][1] = max_needs_matrix[i][1] - assigned_resources_matrix[i][1]; - remaining_needs_matrix[i][2] = max_needs_matrix[i][2] - assigned_resources_matrix[i][2]; - } - if a_remaining > a || b_remaining > b || c_remaining > c { - return (false, vec![]); - } - a_remaining = a - a_remaining; - b_remaining = b - b_remaining; - c_remaining = c - c_remaining; - let mut infinite_detection: u8 = 2; - let mut done: [bool; PROCESS_COUNT] = [false; PROCESS_COUNT]; - let mut q: Vec = Vec::with_capacity(PROCESS_COUNT); - while !done[0] || !done[1] || !done[2] || !done[3] || !done[4] { - infinite_detection -= 1; - - for i in 0..PROCESS_COUNT { - if !done[i] - && a_remaining >= remaining_needs_matrix[i][0] - && b_remaining >= remaining_needs_matrix[i][1] - && c_remaining >= remaining_needs_matrix[i][2] +fn print_matrix(matrix:[[u8;RESOURCE_COUNT];PROCESS_COUNT]) + { + for i in 0..5 { - match a_remaining.checked_sub(remaining_needs_matrix[i][0]) { - Some(result) => { - a_remaining = result; + print!("\n\t Process {}: ", i); + for j in 0..3 + { + if matrix[i][j] > 99 + { + print!(" "); + } + else if matrix[i][j] > 9 + { + print!(" "); + } + else + { + print!(" "); + } + print!("{}", matrix[i][j]); } - None => { - return (false, vec![]); - } - } - match a_remaining.checked_add(max_needs_matrix[i][0]) { - Some(result) => { - a_remaining = result; - } - None => { - return (false, vec![]); - } - } - match b_remaining.checked_sub(remaining_needs_matrix[i][1]) { - Some(result) => { - b_remaining = result; - } - None => { - return (false, vec![]); - } - } - match b_remaining.checked_add(max_needs_matrix[i][1]) { - Some(result) => { - b_remaining = result; - } - None => { - return (false, vec![]); - } - } - match c_remaining.checked_sub(remaining_needs_matrix[i][2]) { - Some(result) => { - c_remaining = result; - } - None => { - return (false, vec![]); - } - } - match c_remaining.checked_add(max_needs_matrix[i][2]) { - Some(result) => { - c_remaining = result; - } - None => { - return (false, vec![]); - } - } - done[i] = true; - q.push(i as u8); - infinite_detection = 2; + println!(); } - } - if infinite_detection == 0 { - return (false, q); - } } - (true, q) -} + +fn banker(a:u8, b:u8, c:u8, max_needs_matrix:[[u8;RESOURCE_COUNT];PROCESS_COUNT], assigned_resources_matrix:[[u8;RESOURCE_COUNT];PROCESS_COUNT]) -> (bool, Vec) + { + let mut a_remaing:u8 = 0; + let mut b_remaing:u8 = 0; + let mut c_remaing:u8 = 0; + let mut remaining_needs_matrix:[[u8;RESOURCE_COUNT];PROCESS_COUNT] = [[0;RESOURCE_COUNT];PROCESS_COUNT]; + for i in 0..PROCESS_COUNT + { + match a_remaing.checked_add(assigned_resources_matrix[i][0]) + { + Some(result) => + { + a_remaing = result; + } + None => + { + return (false, vec![]); + } + } + match b_remaing.checked_add(assigned_resources_matrix[i][1]) + { + Some(result) => + { + b_remaing = result; + } + None => + { + return (false, vec![]); + } + } + match c_remaing.checked_add(assigned_resources_matrix[i][2]) + { + Some(result) => + { + c_remaing = result; + } + None => + { + return (false, vec![]); + } + } + remaining_needs_matrix[i][0] = max_needs_matrix[i][0] - assigned_resources_matrix[i][0]; + remaining_needs_matrix[i][1] = max_needs_matrix[i][1] - assigned_resources_matrix[i][1]; + remaining_needs_matrix[i][2] = max_needs_matrix[i][2] - assigned_resources_matrix[i][2]; + } + if a_remaing > a || b_remaing > b || c_remaing > c + { + return (false, vec![]); + } + a_remaing = a - a_remaing; + b_remaing = b - b_remaing; + c_remaing = c - c_remaing; + let mut infinite_detection:u8 = 2; + let mut done:[bool;PROCESS_COUNT] = [false;PROCESS_COUNT]; + let mut q:Vec = Vec::with_capacity(PROCESS_COUNT); + while !done[0] || !done[1] || !done[2] || !done[3] || !done[4] + { + infinite_detection -= 1; + + for i in 0..PROCESS_COUNT + { + if !done[i] + { + if a_remaing >= remaining_needs_matrix[i][0] && b_remaing >= remaining_needs_matrix[i][1] && c_remaing >= remaining_needs_matrix[i][2] + { + match a_remaing.checked_sub(remaining_needs_matrix[i][0]) + { + Some(result) => + { + a_remaing = result; + } + None => + { + return (false , vec![]); + } + } + match a_remaing.checked_add(max_needs_matrix[i][0]) + { + Some(result) => + { + a_remaing = result; + } + None => + { + return (false, vec![]); + } + } + match b_remaing.checked_sub(remaining_needs_matrix[i][1]) + { + Some(result) => + { + b_remaing = result; + } + None => + { + return (false , vec![]); + } + } + match b_remaing.checked_add(max_needs_matrix[i][1]) + { + Some(result) => + { + b_remaing = result; + } + None => + { + return (false, vec![]); + } + } + match c_remaing.checked_sub(remaining_needs_matrix[i][2]) + { + Some(result) => + { + c_remaing = result; + } + None => + { + return (false , vec![]); + } + } + match c_remaing.checked_add(max_needs_matrix[i][2]) + { + Some(result) => + { + c_remaing = result; + } + None => + { + return (false, vec![]); + } + } + done[i] = true; + q.push(i as u8); + infinite_detection = 2; + } + } + } + if infinite_detection == 0 + { + return (false, q); + } + } + (true, q) + }