working on picasso wu
Signed-off-by: Julien CLEMENT <julien.clement@epita.fr>
This commit is contained in:
1 parent
e11eceaa85
commit
8625c57d1a
15 files changed
+1002
-1
No files matched your search
@@ -0,0 +1,131 @@
|
||||
uint64_t allowed_moves[0x10][0x5] =
|
||||
{
|
||||
[0x0] =
|
||||
{
|
||||
[0x0] = 0x0100000000000000
|
||||
[0x1] = 0x0000100000000000
|
||||
[0x2] = 0x0000000000000000
|
||||
[0x3] = 0x0000000000000000
|
||||
[0x4] = 0x0000000000000000
|
||||
}
|
||||
[0x1] =
|
||||
{
|
||||
[0x0] = 0x1000000000000000
|
||||
[0x1] = 0x0010000000000000
|
||||
[0x2] = 0x0000010000000000
|
||||
[0x3] = 0x0000000000000000
|
||||
[0x4] = 0x0000000000000000
|
||||
}
|
||||
[0x2] =
|
||||
{
|
||||
[0x0] = 0x0100000000000000
|
||||
[0x1] = 0x0001000000000000
|
||||
[0x2] = 0x0000001000000000
|
||||
[0x3] = 0x0000000000000000
|
||||
[0x4] = 0x0000000000000000
|
||||
}
|
||||
[0x3] =
|
||||
{
|
||||
[0x0] = 0x0010000000000000
|
||||
[0x1] = 0x0000000100000000
|
||||
[0x2] = 0x0000000000000000
|
||||
[0x3] = 0x0000000000000000
|
||||
[0x4] = 0x0000000000000000
|
||||
}
|
||||
[0x4] =
|
||||
{
|
||||
[0x0] = 0x1000000000000000
|
||||
[0x1] = 0x0000010000000000
|
||||
[0x2] = 0x0000000010000000
|
||||
[0x3] = 0x0000000000000000
|
||||
[0x4] = 0x0000000000000000
|
||||
}
|
||||
[0x5] =
|
||||
{
|
||||
[0x0] = 0x0100000000000000
|
||||
[0x1] = 0x0000100000000000
|
||||
[0x2] = 0x0000001000000000
|
||||
[0x3] = 0x0000000001000000
|
||||
[0x4] = 0x0000000000000000
|
||||
}
|
||||
[0x6] =
|
||||
{
|
||||
[0x0] = 0x0010000000000000
|
||||
[0x1] = 0x0000010000000000
|
||||
[0x2] = 0x0000000100000000
|
||||
[0x3] = 0x0000000000100000
|
||||
[0x4] = 0x0000000000000000
|
||||
}
|
||||
[0x7] =
|
||||
{
|
||||
[0x0] = 0x0001000000000000
|
||||
[0x1] = 0x0000001000000000
|
||||
[0x2] = 0x0000000000010000
|
||||
[0x3] = 0x0000000000000000
|
||||
[0x4] = 0x0000000000000000
|
||||
}
|
||||
[0x8] =
|
||||
{
|
||||
[0x0] = 0x0000100000000000
|
||||
[0x1] = 0x0000000001000000
|
||||
[0x2] = 0x0000000000001000
|
||||
[0x3] = 0x0000000000000000
|
||||
[0x4] = 0x0000000000000000
|
||||
}
|
||||
[0x9] =
|
||||
{
|
||||
[0x0] = 0x0000010000000000
|
||||
[0x1] = 0x0000000010000000
|
||||
[0x2] = 0x0000000000100000
|
||||
[0x3] = 0x0000000000000100
|
||||
[0x4] = 0x0000000000000000
|
||||
}
|
||||
[0xa] =
|
||||
{
|
||||
[0x0] = 0x0000001000000000
|
||||
[0x1] = 0x0000000001000000
|
||||
[0x2] = 0x0000000000010000
|
||||
[0x3] = 0x0000000000000010
|
||||
[0x4] = 0x0000000000000000
|
||||
}
|
||||
[0xb] =
|
||||
{
|
||||
[0x0] = 0x0000000100000000
|
||||
[0x1] = 0x0000000000100000
|
||||
[0x2] = 0x0000000000000001
|
||||
[0x3] = 0x0000000000000000
|
||||
[0x4] = 0x0000000000000000
|
||||
}
|
||||
[0xc] =
|
||||
{
|
||||
[0x0] = 0x0000000010000000
|
||||
[0x1] = 0x0000000000000100
|
||||
[0x2] = 0x0000000000000000
|
||||
[0x3] = 0x0000000000000000
|
||||
[0x4] = 0x0000000000000000
|
||||
}
|
||||
[0xd] =
|
||||
{
|
||||
[0x0] = 0x0000000001000000
|
||||
[0x1] = 0x0000000000001000
|
||||
[0x2] = 0x0000000000000010
|
||||
[0x3] = 0x0000000000000000
|
||||
[0x4] = 0x0000000000000000
|
||||
}
|
||||
[0xe] =
|
||||
{
|
||||
[0x0] = 0x0000000000100000
|
||||
[0x1] = 0x0000000000000100
|
||||
[0x2] = 0x0000000000000001
|
||||
[0x3] = 0x0000000000000000
|
||||
[0x4] = 0x0000000000000000
|
||||
}
|
||||
[0xf] =
|
||||
{
|
||||
[0x0] = 0x0000000000010000
|
||||
[0x1] = 0x0000000000000010
|
||||
[0x2] = 0x0000000000000000
|
||||
[0x3] = 0x0000000000000000
|
||||
[0x4] = 0x0000000000000000
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 88 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
@@ -0,0 +1,71 @@
|
||||
char init_state[0x36] =
|
||||
{
|
||||
0x0d, 0x03, 0x02, 0x0e, 0x0f, 0x09, 0x07, 0x0e, 0x0d, 0x06, 0x03, 0x02, 0x07, 0x02, 0x08, 0x0e,
|
||||
0x07, 0x04, 0x04, 0x03, 0x0d, 0x04, 0x0c, 0x03, 0x0f, 0x02, 0x0a, 0x05, 0x09, 0x01, 0x06, 0x0a,
|
||||
0x0b, 0x02, 0x05, 0x0c, 0x0e, 0x0b, 0x0d, 0x01, 0x0a, 0x01, 0x05, 0x09, 0x01, 0x0f, 0x06, 0x0e,
|
||||
0x04, 0x04, 0x0b, 0x04, 0x0b, 0x0f, 0x00
|
||||
};
|
||||
|
||||
|
||||
int32_t main(int32_t argc, char** argv, char** envp)
|
||||
{
|
||||
char* const init_state_ptr = &init_state;
|
||||
char state[0x36];
|
||||
char* state_ptr = &state;
|
||||
for (int64_t size = 0x36; size != 0; size -= 1)
|
||||
{
|
||||
*state_ptr = *init_state_ptr;
|
||||
state_ptr += 1;
|
||||
init_state_ptr += 1;
|
||||
}
|
||||
|
||||
printf("Password: ", init_state_ptr);
|
||||
fflush(stdout);
|
||||
|
||||
char input[0x18];
|
||||
scanf("%24s", &input);
|
||||
|
||||
int64_t state_index = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (strlen(&input) <= state_index)
|
||||
{
|
||||
// Cutting everything that happens
|
||||
...
|
||||
if (check == OK)
|
||||
{
|
||||
puts("Win!");
|
||||
FILE file = fopen("flag.txt", &rb);
|
||||
if (file != NULL)
|
||||
{
|
||||
char flag[0x46];
|
||||
fread(&flag, 1, 0x46, file);
|
||||
fclose(file);
|
||||
puts(flag);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
puts("Send your input on the remote se…");
|
||||
}
|
||||
else
|
||||
puts("Nope!");
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
char* pos_ptr = strchr("abcdefghjklmnpqrstuvwxyz", input[state_index]);
|
||||
if (pos_ptr != NULL)
|
||||
{
|
||||
// Do stuff iterating on the state
|
||||
...
|
||||
state_index += 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
puts("Nope!");
|
||||
break;
|
||||
}
|
||||
exit(1);
|
||||
/* no return */
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
@@ -0,0 +1,37 @@
|
||||
else
|
||||
{
|
||||
char* pos_ptr = strchr("abcdefghjklmnpqrstuvwxyz", input[state_index]);
|
||||
if (pos_ptr != NULL)
|
||||
{
|
||||
int64_t pos = pos_ptr - "abcdefghjklmnpqrstuvwxyz";
|
||||
int32_t remainder = pos % 4;
|
||||
char* permutation_array = &permutations[pos / 4];
|
||||
while (true)
|
||||
{
|
||||
if (remainder < 1)
|
||||
break;
|
||||
remainder -= 1;
|
||||
|
||||
char state_copy[0x36];
|
||||
char* state_copy_ptr = &state_copy;
|
||||
|
||||
char* state_ptr_1 = &state;
|
||||
|
||||
int64_t i = 0x36;
|
||||
for (; i != 0; i -= 1)
|
||||
{
|
||||
*state_copy_ptr = *state_ptr_1;
|
||||
state_copy_ptr += 1;
|
||||
state_ptr_1 += 1;
|
||||
}
|
||||
do
|
||||
{
|
||||
char elem = state_copy[permutation_array[i]];
|
||||
state[i] = elem;
|
||||
i += 1
|
||||
} while (i != 0x36);
|
||||
}
|
||||
state_index += 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
char permutations[0x6][0x36] =
|
||||
{
|
||||
[0x0] =
|
||||
{
|
||||
[0x00] = 0x09
|
||||
[0x01] = 0x01
|
||||
[0x02] = 0x02
|
||||
[0x03] = 0x0c
|
||||
[0x04] = 0x04
|
||||
[0x05] = 0x05
|
||||
[0x06] = 0x0f
|
||||
[0x07] = 0x07
|
||||
[0x08] = 0x08
|
||||
[0x09] = 0x2d
|
||||
...
|
||||
[0x34] = 0x34
|
||||
[0x35] = 0x35
|
||||
}
|
||||
[0x1] =
|
||||
{
|
||||
[0x00] = 0x00
|
||||
[0x01] = 0x01
|
||||
[0x02] = 0x2a
|
||||
[0x03] = 0x03
|
||||
...
|
||||
[0x34] = 0x34
|
||||
[0x35] = 0x11
|
||||
[0x2] =
|
||||
{
|
||||
[0x00] = 0x02
|
||||
[0x01] = 0x05
|
||||
...
|
||||
[0x35] = 0x35
|
||||
}
|
||||
[0x3] =
|
||||
{
|
||||
[0x00] = 0x00
|
||||
[0x01] = 0x01
|
||||
...
|
||||
[0x35] = 0x33
|
||||
}
|
||||
[0x4] =
|
||||
{
|
||||
[0x00] = 0x00
|
||||
[0x01] = 0x01
|
||||
...
|
||||
[0x35] = 0x35
|
||||
}
|
||||
[0x5] =
|
||||
{
|
||||
[0x00] = 0x21
|
||||
[0x01] = 0x1e
|
||||
...
|
||||
[0x35] = 0x14
|
||||
}
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,67 @@
|
||||
if (strlen(&input) <= state_index)
|
||||
{
|
||||
int64_t board = 0x3da8e0915f2c4b67;
|
||||
int64_t next_board;
|
||||
int64_t i = 0;
|
||||
uint64_t move;
|
||||
while (true)
|
||||
{
|
||||
uint64_t c = state[i];
|
||||
void* allowed_moves = &allowed_moves;
|
||||
int32_t shifter = 0x3c;
|
||||
do
|
||||
{
|
||||
if (c == ((board >> shifter) & 0xf))
|
||||
{
|
||||
uint64_t* moves = allowed_moves;
|
||||
do
|
||||
{
|
||||
move = *moves;
|
||||
|
||||
if (move == 0)
|
||||
break;
|
||||
|
||||
moves += 1;
|
||||
} while (((move * 0xf) & board) != 0);
|
||||
|
||||
if (move != 0)
|
||||
break;
|
||||
}
|
||||
shifter -= 4;
|
||||
allowed_moves += 0x28;
|
||||
} while (shifter != 0xfffffffc);
|
||||
|
||||
if (c != ((board >> shifter) & 0xf) || move == 0)
|
||||
break;
|
||||
|
||||
int64_t swapper = ((c * move) ^ (c << shifter));
|
||||
next_board = (board ^ swapper);
|
||||
if (board == swapper)
|
||||
break;
|
||||
|
||||
i += 1;
|
||||
|
||||
if (i == 0x36)
|
||||
break;
|
||||
|
||||
board = next_board;
|
||||
}
|
||||
if (next_board == 0x123456789abcdef0)
|
||||
{
|
||||
puts("Win!");
|
||||
FILE file = fopen("flag.txt", &rb);
|
||||
if (file != NULL)
|
||||
{
|
||||
char flag[0x46];
|
||||
fread(&flag, 1, 0x46, file);
|
||||
fclose(file);
|
||||
puts(flag);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
puts("Send your input on the remote se…");
|
||||
}
|
||||
else
|
||||
puts("Nope!");
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
struct Board {
|
||||
board: [usize; 0x10],
|
||||
moves: Vec<usize>,
|
||||
max_moves: usize,
|
||||
move_number: usize,
|
||||
|
||||
empt_idx: usize,
|
||||
|
||||
|
||||
solved_grid: [usize; 0x10],
|
||||
|
||||
fixed_moves: HashMap<usize, usize>,
|
||||
|
||||
move_limit: [isize; 0x10]
|
||||
}
|
||||
|
||||
impl Board {
|
||||
pub fn new(board: [usize; 0x10]) -> Self {
|
||||
let empt_idx: usize = board.iter().position(|&r| r == 0).unwrap().try_into().unwrap();
|
||||
let all_moves: [usize; 0x36] = [
|
||||
0x0d, 0x03, 0x02, 0x0e, 0x0f, 0x09, 0x07, 0x0e, 0x0d, 0x06, 0x03, 0x02, 0x07, 0x02, 0x08, 0x0e,
|
||||
0x07, 0x04, 0x04, 0x03, 0x0d, 0x04, 0x0c, 0x03, 0x0f, 0x02, 0x0a, 0x05, 0x09, 0x01, 0x06, 0x0a,
|
||||
0x0b, 0x02, 0x05, 0x0c, 0x0e, 0x0b, 0x0d, 0x01, 0x0a, 0x01, 0x05, 0x09, 0x01, 0x0f, 0x06, 0x0e,
|
||||
0x04, 0x04, 0x0b, 0x04, 0x0b, 0x0f
|
||||
];
|
||||
let solved_grid: [usize; 0x10] = [1,2,3,4,5,6,7,8,9,0xa,0xb,0xc,0xd,0xe,0xf,0];
|
||||
|
||||
let mut fixed_moves: HashMap<usize, usize> = HashMap::new();
|
||||
|
||||
for i in vec![4, 0xd, 0x16, 0x1f, 0x28, 0x31] {
|
||||
fixed_moves.insert(i, all_moves[i]);
|
||||
}
|
||||
|
||||
let mut move_limit: [isize; 0x10] = [0; 0x10];
|
||||
|
||||
for mv in all_moves.iter() {
|
||||
move_limit[*mv] += 1;
|
||||
}
|
||||
|
||||
Board {
|
||||
board: board,
|
||||
moves: Vec::new(),
|
||||
max_moves: 0x36,
|
||||
move_number: 0,
|
||||
empt_idx: empt_idx,
|
||||
solved_grid: solved_grid,
|
||||
fixed_moves: fixed_moves,
|
||||
move_limit: move_limit,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn solved(&self) -> bool {
|
||||
self.board == self.solved_grid
|
||||
}
|
||||
|
||||
pub fn get_move(&self, off: Vec<isize>) -> Option<usize> {
|
||||
let empt_idx: isize = self.empt_idx.try_into().unwrap();
|
||||
let empt_i: isize = empt_idx / 4;
|
||||
let empt_j: isize = empt_idx % 4;
|
||||
let src_i: isize = empt_i + off[0];
|
||||
let src_j: isize = empt_j + off[1];
|
||||
if src_i < 4 && src_i >= 0 && src_j < 4 && src_j >= 0 {
|
||||
let idx: usize = (src_i * 4 + src_j).try_into().unwrap();
|
||||
return Some(self.board[idx])
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn generate_moves(&self) -> Vec<usize> {
|
||||
let mut moves: Vec<usize> = Vec::new();
|
||||
|
||||
for off in vec![vec![-1, 0], vec![1, 0], vec![0, -1], vec![0, 1]] {
|
||||
let maybe_move = self.get_move(off);
|
||||
if let Some(mv) = maybe_move {
|
||||
moves.push(mv);
|
||||
}
|
||||
}
|
||||
|
||||
moves
|
||||
}
|
||||
|
||||
pub fn apply_move(&mut self, mv: usize, undo: bool) {
|
||||
let i: usize = self.board.iter().position(|&x| x == mv).unwrap();
|
||||
let tmp: usize = self.board[i];
|
||||
self.board[i] = self.board[self.empt_idx];
|
||||
self.board[self.empt_idx] = tmp;
|
||||
self.empt_idx = i;
|
||||
if undo {
|
||||
self.move_number -= 1;
|
||||
self.moves.pop();
|
||||
self.move_limit[mv] += 1;
|
||||
}
|
||||
else {
|
||||
self.move_number += 1;
|
||||
self.moves.push(mv);
|
||||
self.move_limit[mv] -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn manhattan_distance(&self, mv: usize) -> isize {
|
||||
let mv_idx: isize = self.board.iter().position(|&x| x == mv).unwrap().try_into().unwrap();
|
||||
let mv_i: isize = mv_idx / 4;
|
||||
let mv_j: isize = mv_idx % 4;
|
||||
|
||||
let supposed_idx: isize = (mv - 1).try_into().unwrap();
|
||||
let supposed_i: isize = supposed_idx / 4;
|
||||
let supposed_j: isize = supposed_idx % 4;
|
||||
|
||||
let manhattan: isize = (supposed_j - mv_j).abs() + (supposed_i - mv_i).abs();
|
||||
|
||||
manhattan
|
||||
}
|
||||
|
||||
pub fn solve(&mut self) -> bool {
|
||||
|
||||
// GG
|
||||
if self.solved() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// No more moves
|
||||
if self.move_number >= self.max_moves {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Last move need to be 0xc or 0xf
|
||||
if self.move_limit[0xc] <= 0 && self.move_limit[0xf] <= 0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
let last_move: Option<usize> = self.moves.last().copied();
|
||||
|
||||
if let Some(mv) = last_move {
|
||||
// Tile cannot possibly go back to its supposed location
|
||||
let man: isize = self.manhattan_distance(mv);
|
||||
if self.move_limit[mv] < man {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Generate possible moves from current grid
|
||||
let mut moves: Vec<usize> = self.generate_moves();
|
||||
|
||||
// Cannot apply same move twice
|
||||
if let Some(mv) = last_move {
|
||||
moves = moves.iter().filter(|&x| *x != mv).cloned().collect();
|
||||
}
|
||||
|
||||
// Filter fixed moves from the cube center tiles
|
||||
if self.fixed_moves.contains_key(&self.move_number) {
|
||||
let mv: usize = *self.fixed_moves.get(&self.move_number).unwrap();
|
||||
moves = moves.iter().filter(|&x| *x == mv).cloned().collect();
|
||||
}
|
||||
|
||||
|
||||
for mv in moves {
|
||||
// Apply move
|
||||
self.apply_move(mv, false);
|
||||
// Recursive call
|
||||
let solved: bool = self.solve();
|
||||
// GG
|
||||
if solved {
|
||||
return true;
|
||||
}
|
||||
// Undo move
|
||||
self.apply_move(mv, true);
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn solve() {
|
||||
let arr: [usize; 0x10] = [
|
||||
3, 0xd, 0xa, 8,
|
||||
0xe, 0, 9, 1,
|
||||
5, 0xf, 2, 0xc,
|
||||
4, 0xb, 6, 7
|
||||
];
|
||||
|
||||
let mut board: Board = Board::new(arr);
|
||||
|
||||
board.solve();
|
||||
|
||||
println!("{:x?}", board.moves);
|
||||
println!("{}", board.moves.len())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
solve()
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |