a3 tests
This commit is contained in:
152
Aufgabe3-HexMax/src/lib.rs
Normal file
152
Aufgabe3-HexMax/src/lib.rs
Normal file
@ -0,0 +1,152 @@
|
||||
use std::fs;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Move {
|
||||
digit: u8,
|
||||
put: u16,
|
||||
taken: u16,
|
||||
}
|
||||
|
||||
pub struct DigitHistory {
|
||||
pub original_digit: u8,
|
||||
move_option: Option<Move>,
|
||||
}
|
||||
|
||||
pub struct PutTaken {
|
||||
pub digit_i: usize,
|
||||
pub stick_map: u8,
|
||||
}
|
||||
|
||||
pub const HEX: [u8; 16] = [
|
||||
0b1110111, // 0
|
||||
0b0010010, // 1
|
||||
0b1011101, // 2
|
||||
0b1011011, // 3
|
||||
0b0111010, // 4
|
||||
0b1101011, // 5
|
||||
0b1101111, // 6
|
||||
0b1010010, // 7
|
||||
0b1111111, // 8
|
||||
0b1111011, // 9
|
||||
0b1111110, // A
|
||||
0b0101111, // B
|
||||
0b1100101, // C
|
||||
0b0011111, // D
|
||||
0b1101101, // E
|
||||
0b1101100, // F
|
||||
];
|
||||
|
||||
pub fn largest_hex(filepath: &str) -> (Vec<DigitHistory>, u16) {
|
||||
let mut digits: Vec<DigitHistory>;
|
||||
let max_swaps: u16;
|
||||
{
|
||||
let content = fs::read_to_string(filepath).unwrap();
|
||||
let mut lines = content.lines();
|
||||
let line = lines.next().unwrap();
|
||||
digits = Vec::with_capacity(line.len());
|
||||
for character in line.chars() {
|
||||
digits.push(DigitHistory {
|
||||
original_digit: character.to_digit(16).unwrap() as u8,
|
||||
move_option: None,
|
||||
});
|
||||
}
|
||||
max_swaps = lines.next().unwrap().parse().unwrap();
|
||||
}
|
||||
{
|
||||
let mut total_put: u16 = 0;
|
||||
let mut total_taken: u16 = 0;
|
||||
while total_taken != total_put || total_put != max_swaps {
|
||||
for DigitHistory {original_digit, move_option} in digits.iter_mut() {
|
||||
if move_option.is_some() {continue;}
|
||||
let digit_hex = HEX[*original_digit as usize];
|
||||
for (j, to_digit) in HEX.iter().enumerate().rev() {
|
||||
if j <= *original_digit as usize {break;}
|
||||
let put: u16 = amount_put(digit_hex, *to_digit);
|
||||
let taken: u16 = amount_put(*to_digit, digit_hex);
|
||||
if total_put + put <= max_swaps && total_taken + taken <= max_swaps {
|
||||
total_put += put;
|
||||
total_taken += taken;
|
||||
*move_option = Some(Move {
|
||||
digit: j as u8,
|
||||
put,
|
||||
taken,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for DigitHistory {original_digit, move_option} in digits.iter_mut().rev() {
|
||||
if total_put == total_taken {break;}
|
||||
let mut put_with_undo = total_put;
|
||||
let mut taken_with_undo = total_taken;
|
||||
if let Some(moved) = move_option {
|
||||
put_with_undo -= moved.put;
|
||||
taken_with_undo -= moved.taken;
|
||||
}
|
||||
let digit_hex = HEX[*original_digit as usize];
|
||||
let mut best_move: Option<Move> = None;
|
||||
let mut best_diff = i16::MAX;
|
||||
for (j, to_digit) in HEX.iter().enumerate().rev() {
|
||||
let put = amount_put(digit_hex, *to_digit);
|
||||
let taken = amount_put(*to_digit, digit_hex);
|
||||
let new_total_put = put_with_undo + put;
|
||||
let new_total_taken = taken_with_undo + taken;
|
||||
let new_diff = (new_total_put as i16 - new_total_taken as i16).abs();
|
||||
if new_diff < (total_put as i16 - total_taken as i16).abs() &&
|
||||
new_total_taken <= max_swaps && new_total_put <= max_swaps && new_diff < best_diff {
|
||||
best_diff = new_diff;
|
||||
best_move = Some(Move {
|
||||
digit: j as u8,
|
||||
put,
|
||||
taken,
|
||||
});
|
||||
}
|
||||
}
|
||||
if let Some(moved) = best_move {
|
||||
*move_option = best_move;
|
||||
total_put = put_with_undo + moved.put;
|
||||
total_taken = taken_with_undo + moved.taken;
|
||||
}
|
||||
}
|
||||
}
|
||||
(digits, max_swaps)
|
||||
}
|
||||
}
|
||||
|
||||
fn amount_put(from: u8, to: u8) -> u16 {
|
||||
((from ^ to) & to).count_ones() as u16
|
||||
}
|
||||
|
||||
pub fn to_hex_str(digits: &[DigitHistory]) -> String {
|
||||
let mut largest_hex_str = String::with_capacity(digits.len());
|
||||
for digit in digits {
|
||||
largest_hex_str += &format!("{:X}", digit.move_option.map_or(digit.original_digit, |m| m.digit));
|
||||
}
|
||||
largest_hex_str
|
||||
}
|
||||
|
||||
pub fn gen_swaps(digits: &[DigitHistory], number_of_swaps: usize) -> (Vec<PutTaken>, Vec<PutTaken>) {
|
||||
let mut moves_put: Vec<PutTaken> = Vec::with_capacity(number_of_swaps);
|
||||
let mut moves_taken: Vec<PutTaken> = Vec::with_capacity(number_of_swaps);
|
||||
for (j, DigitHistory {original_digit, move_option}) in digits.iter().enumerate() {
|
||||
if let Some(moved) = move_option {
|
||||
let from_hex = HEX[*original_digit as usize];
|
||||
let to_hex = HEX[moved.digit as usize];
|
||||
let changed = from_hex ^ to_hex;
|
||||
let put = changed & to_hex;
|
||||
let taken = changed & from_hex;
|
||||
for (put_or_taken, moves_put_or_taken) in [(put, &mut moves_put), (taken, &mut moves_taken)] {
|
||||
for i in 0..u8::BITS {
|
||||
let stick_map = put_or_taken & 1 << i;
|
||||
if stick_map != 0 {
|
||||
moves_put_or_taken.push(PutTaken {
|
||||
digit_i: j,
|
||||
stick_map,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
(moves_put, moves_taken)
|
||||
}
|
||||
@ -1,180 +1,37 @@
|
||||
use clap::Parser;
|
||||
use std::fs;
|
||||
use hexmax;
|
||||
|
||||
#[derive(Parser)]
|
||||
struct Args {
|
||||
/// Dateipfad der Eingabedatei
|
||||
filepath: String,
|
||||
|
||||
/// Ausgabe von Debuginformationen
|
||||
#[clap(short, long)]
|
||||
debug: bool,
|
||||
|
||||
/// Ausgabe der Umlegungen
|
||||
#[clap(short, long)]
|
||||
swap_print: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Move {
|
||||
digit: u8,
|
||||
put: u16,
|
||||
taken: u16,
|
||||
}
|
||||
|
||||
struct DigitHistory {
|
||||
original_digit: u8,
|
||||
move_option: Option<Move>,
|
||||
}
|
||||
|
||||
struct PutTaken {
|
||||
digit_i: usize,
|
||||
stick_map: u8,
|
||||
}
|
||||
|
||||
const HEX: [u8; 16] = [
|
||||
0b1110111, // 0
|
||||
0b0010010, // 1
|
||||
0b1011101, // 2
|
||||
0b1011011, // 3
|
||||
0b0111010, // 4
|
||||
0b1101011, // 5
|
||||
0b1101111, // 6
|
||||
0b1010010, // 7
|
||||
0b1111111, // 8
|
||||
0b1111011, // 9
|
||||
0b1111110, // A
|
||||
0b0101111, // B
|
||||
0b1100101, // C
|
||||
0b0011111, // D
|
||||
0b1101101, // E
|
||||
0b1101100, // F
|
||||
];
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
let mut digits: Vec<DigitHistory>;
|
||||
let max_swaps: u16;
|
||||
{
|
||||
let content = fs::read_to_string(args.filepath).unwrap();
|
||||
let mut lines = content.lines();
|
||||
let line = lines.next().unwrap();
|
||||
digits = Vec::with_capacity(line.len());
|
||||
for character in line.chars() {
|
||||
digits.push(DigitHistory {
|
||||
original_digit: character.to_digit(16).unwrap() as u8,
|
||||
move_option: None,
|
||||
});
|
||||
}
|
||||
max_swaps = lines.next().unwrap().parse().unwrap();
|
||||
}
|
||||
{
|
||||
let mut total_put: u16 = 0;
|
||||
let mut total_taken: u16 = 0;
|
||||
while total_taken != total_put || total_put != max_swaps {
|
||||
for DigitHistory {original_digit, move_option} in digits.iter_mut() {
|
||||
if move_option.is_some() {continue;}
|
||||
let digit_hex = HEX[*original_digit as usize];
|
||||
for (j, to_digit) in HEX.iter().enumerate().rev() {
|
||||
if j <= *original_digit as usize {break;}
|
||||
let put: u16 = amount_put(digit_hex, *to_digit);
|
||||
let taken: u16 = amount_put(*to_digit, digit_hex);
|
||||
if total_put + put <= max_swaps && total_taken + taken <= max_swaps {
|
||||
total_put += put;
|
||||
total_taken += taken;
|
||||
*move_option = Some(Move {
|
||||
digit: j as u8,
|
||||
put,
|
||||
taken,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for DigitHistory {original_digit, move_option} in digits.iter_mut().rev() {
|
||||
if total_put == total_taken {break;}
|
||||
let mut put_with_undo = total_put;
|
||||
let mut taken_with_undo = total_taken;
|
||||
if let Some(moved) = move_option {
|
||||
put_with_undo -= moved.put;
|
||||
taken_with_undo -= moved.taken;
|
||||
}
|
||||
let digit_hex = HEX[*original_digit as usize];
|
||||
let mut best_move: Option<Move> = None;
|
||||
let mut best_diff = i16::MAX;
|
||||
for (j, to_digit) in HEX.iter().enumerate().rev() {
|
||||
let put = amount_put(digit_hex, *to_digit);
|
||||
let taken = amount_put(*to_digit, digit_hex);
|
||||
let new_total_put = put_with_undo + put;
|
||||
let new_total_taken = taken_with_undo + taken;
|
||||
let new_diff = (new_total_put as i16 - new_total_taken as i16).abs();
|
||||
if new_diff < (total_put as i16 - total_taken as i16).abs() &&
|
||||
new_total_taken <= max_swaps && new_total_put <= max_swaps && new_diff < best_diff {
|
||||
best_diff = new_diff;
|
||||
best_move = Some(Move {
|
||||
digit: j as u8,
|
||||
put,
|
||||
taken,
|
||||
});
|
||||
}
|
||||
}
|
||||
if let Some(moved) = best_move {
|
||||
*move_option = best_move;
|
||||
total_put = put_with_undo + moved.put;
|
||||
total_taken = taken_with_undo + moved.taken;
|
||||
}
|
||||
}
|
||||
}
|
||||
for digit in &digits {
|
||||
print!("{:X}", digit.move_option.map_or(digit.original_digit, |m| m.digit));
|
||||
}
|
||||
println!();
|
||||
if args.debug {println!("genommen: {}, hingelegt: {}", total_taken, total_put);}
|
||||
let (digits, number_of_swaps) = hexmax::largest_hex(&args.filepath);
|
||||
println!("{}", hexmax::to_hex_str(&digits));
|
||||
if args.swap_print {
|
||||
let mut moves_put: Vec<PutTaken> = Vec::with_capacity(total_put as usize);
|
||||
let mut moves_taken: Vec<PutTaken> = Vec::with_capacity(total_taken as usize);
|
||||
for (j, DigitHistory {original_digit, move_option}) in digits.iter().enumerate() {
|
||||
if let Some(moved) = move_option {
|
||||
let from_hex = HEX[*original_digit as usize];
|
||||
let to_hex = HEX[moved.digit as usize];
|
||||
let changed = from_hex ^ to_hex;
|
||||
let put = changed & to_hex;
|
||||
let taken = changed & from_hex;
|
||||
for (put_or_taken, moves_put_or_taken) in [(put, &mut moves_put), (taken, &mut moves_taken)] {
|
||||
for i in 0..u8::BITS {
|
||||
let stick_map = put_or_taken & 1 << i;
|
||||
if stick_map != 0 {
|
||||
moves_put_or_taken.push(PutTaken {
|
||||
digit_i: j,
|
||||
stick_map,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
let (moves_put, moves_taken) = hexmax::gen_swaps(&digits, number_of_swaps as usize);
|
||||
let mut digits_hex: Vec<u8> = digits.iter()
|
||||
.map(|digit| HEX[digit.original_digit as usize]).collect();
|
||||
.map(|digit| hexmax::HEX[digit.original_digit as usize]).collect();
|
||||
println!("Umlegungen:");
|
||||
swap_print(&digits_hex);
|
||||
println!();
|
||||
let mut not_first = false;
|
||||
for (move_put, move_taken) in moves_put.iter().zip(&moves_taken) {
|
||||
if not_first {println!();}
|
||||
for PutTaken {digit_i, stick_map} in [move_put, move_taken] {
|
||||
for hexmax::PutTaken {digit_i, stick_map} in [move_put, move_taken] {
|
||||
digits_hex[*digit_i] ^= stick_map;
|
||||
}
|
||||
swap_print(&digits_hex);
|
||||
not_first = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn amount_put(from: u8, to: u8) -> u16 {
|
||||
((from ^ to) & to).count_ones() as u16
|
||||
}
|
||||
|
||||
fn swap_print(digits_hex: &[u8]) {
|
||||
|
||||
55
Aufgabe3-HexMax/tests/test.rs
Normal file
55
Aufgabe3-HexMax/tests/test.rs
Normal file
@ -0,0 +1,55 @@
|
||||
use hexmax;
|
||||
|
||||
fn test(filepath: &str, expected_result: &str) {
|
||||
assert_eq!(hexmax::to_hex_str(&hexmax::largest_hex(filepath).0), expected_result);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_0() {
|
||||
test("beispieldaten/hexmax0.txt", "EE4");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_1() {
|
||||
test("beispieldaten/hexmax1.txt", "FFFEA97B55");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_2() {
|
||||
test("beispieldaten/hexmax2.txt", "FFFFFFFFFFFFFFFFD9A9BEAEE8EDA8BDA989D9F8");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_3() {
|
||||
test("beispieldaten/hexmax3.txt",
|
||||
concat!("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FAA98BB8B9DFAFEAE888DD888AD8BA8EA8888"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_4() {
|
||||
test("beispieldaten/hexmax4.txt",
|
||||
concat!("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEB8DE88BAA8ADD888898E9BA8",
|
||||
"8AD98988F898AB7AF7BDA8A61BA7D4AD8F888"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_5() {
|
||||
test("beispieldaten/hexmax5.txt",
|
||||
concat!("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF88EFA9EBE89EFA99FBDAA8",
|
||||
"E8EAD88AB899F8E8F9AA9E9AD88988EDA9A99888EDAD989A8BAFD8A88888888",
|
||||
"888888888888888888888888888888888888888888888888888888888888888",
|
||||
"888888888888888888888888888888888888888888888888888888888888888",
|
||||
"888888888888888888888888888888888888888888888888888888888888888",
|
||||
"8888888888888888888888888888888888888888888888888888888"));
|
||||
}
|
||||
Reference in New Issue
Block a user