Created
January 21, 2024 12:19
-
-
Save foxtran/632a121d444a89dcba5c49d17202cddb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module helper_mod { | |
public i32 sudctoi(c8 c) { | |
consteval i32 C0 = i32('0'), C9 = i32('9'), CA = i32('A'), CZ = i32('Z') | |
if (irepr >= C0 .and. irepr <= C9) { | |
return i32(c) - C0 | |
} else if (irepr >= CA .and. irepr <= CZ) { | |
return i32(c) - CA + 10 | |
} else { | |
return 0 | |
} | |
} | |
public c8 itosudc(i32 i) | |
if (i == 0) { | |
return '.' | |
} else if (i < 10) { | |
return c8(i+i32('0')) | |
} else { | |
return c8(i-10+i32('A')) | |
} | |
} | |
} | |
module sudoku_solver { | |
public type sudoku_solver_t { | |
i32 n, n2 | |
allocatable i32[:,:] field | |
allocatable i32[:,:,:] tfield | |
none load_from_file(File) | |
bool next() | |
none print() | |
} | |
sudoku_solver_t.load_from_file(File LU) { | |
use helper_mod -> global, only: sudctoi | |
allocatable c8[:] line | |
read(LU, fmt="(I)", this.n) | |
this.n2 = this.n * this.n | |
if (this%n < 1) { | |
fatal("Negate field size!") | |
} | |
if (this%n > 6) { | |
fatal("Unsupported size!") | |
} | |
this.field = new(fill=0) i32[this.n2, this.n2] | |
this.tfield = new(fill=0) i32[this.n2, this.n2, this.n2] | |
line = new(fill=' ') c8[this.n2] | |
do i32 i = 1, this%n2 { | |
read(LU, fmt=f"(A{this.n2})", line) | |
do i32 j = 1, this%n2 { | |
this.field[i,j] = sudctoi(line[j]) | |
} | |
} | |
} | |
bool sudoku_solver_t.next() { | |
integer :: pos(1) | |
next = .false. | |
this%tfield[..] = -1 | |
do i32 n = 1, this%n2 { | |
if (count(this.field[..] == n) == this.n2) { | |
this.tfield[..,n] = 0 | |
cycle | |
} | |
do i32 j = 1, this.n2 { | |
do i32 i = 1, this.n2 { | |
if (this%tfield[i,j,n] == 0) { | |
cycle | |
} | |
if (this%field[i,j] == n) { | |
this%tfield[i,j,:] = 0 | |
this%tfield[:,j,n] = 0 | |
this%tfield[i,:,n] = 0 | |
! fill block | |
i32 imin = ((i-1) / this.n) * this%n + 1 | |
i32 jmin = ((j-1) / this.n) * this%n + 1 | |
i32 imax = imin + this.n - 1 | |
i32 jmax = jmin + this.n - 1 | |
this%tfield[imin:imax, jmin:jmax, n] = 0 | |
} | |
} | |
} | |
} | |
do i32 j = 1, this.n2 { | |
do i32 i = 1, this.n2 { | |
if (count(this.tfield[i,j,:] == -1) == 1) { | |
next = .true. | |
pos = findloc(this.tfield[i,j,:], -1) | |
this%field[i,j] = pos(1) | |
} | |
} | |
} | |
if (next .and. count(this.field[..] == 0) == 0) next = .false. | |
} | |
sudoku_solver_t.print() { | |
use helper_mod -> global, only: itosudc | |
print_horizontal() | |
do i32 i = 1, this%n2 { | |
do i32 j = 1, this%n2 { | |
if (j % this.n == 1) { | |
write(*, fmt="(A3)", " | ") | |
} | |
write(*, fmt="(A1)", itosudc(this%field[i,j])) | |
} | |
write(*, fmt="(A3)", " |\n") | |
if (i % this.n == 0) print_horizontal() | |
} | |
nested print_horizontal() { | |
write(*, fmt="(A3)", " +-") | |
do i32 j = 1, this.n { | |
write(*, fmt=f"(A{this.n})", this.n * "-") | |
if (j < this.n) write(*, fmt="(A3)", "-+-") | |
} | |
write(*, fmt="(A3)", "-+\n") | |
} | |
} | |
} | |
program sudoku_solver() { | |
use sudoku_solver_mod -> global | |
sudoku_solver_t ss | |
i32 n | |
File LU | |
bool do_next, file_exist | |
allocatable c8[:] filename | |
call get_command_argument(1, filename) | |
inquire(file=filename, exist=file_exist) | |
if (.not.file_exist) fatal(f"File '{filename}' not found!") | |
open(newunit=LU, file=filename, form='formatted') | |
ss.load_from_file(LU) | |
close(LU) | |
ss.print() | |
do_next = .true. | |
do while (do_next) { | |
do_next = ss.next() | |
ss.print() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment