Commit 3da806bc authored by Seblu's avatar Seblu
Browse files

No commit message

No commit message
parent d00c5e24
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -2,10 +2,10 @@

all: sudoku

sudoku: sudoku.o sudoku.hh
	g++ -Wall -Wextra -pedantic -ansi -g $< -o $@
sudoku: sudoku.o grid.o
	g++ -Wall -Wextra -pedantic -ansi -g $^ -o $@

%.o:%.cc
%.o:%.cc sudoku.hh
	g++ -Wall -Wextra -pedantic -ansi -g $< -o $@ -c

clean:

grid.cc

0 → 100644
+145 −0
Original line number Diff line number Diff line
#include "sudoku.hh"

bool Grid::verbose = false;
bool Grid::advprint = false;

int Grid::load(const char *filename)
{
  int val;
  std::fstream fs;

  assert(filename);
  if (Grid::verbose)
    std::cout << "Loading file: " << filename << "..." << std::endl;
  fs.open(filename, std::fstream::in);
  if (!fs.is_open())
    return 0;
  for (int i = 0; i < GRID_SIDE; ++i)
    for (int j = 0; j < GRID_SIDE; ++j) {
      fs >> std::dec >> val;
      if (val < 0 || val > 9) {
	std::cerr << "Invalid value in file: " << val << std::endl;
	exit(EXIT_LOADFAIL);
      }
      if (val > 0)
	pose(i, j, val);
      //block_[i][j].set(val);
    }
  fs.close();
  return 1;
}

void Grid::pose(int x, int y, int v)
{
  if (x < 0 || x >= GRID_SIDE || y < 0 || y >= GRID_SIDE) {
    std::cerr << "Invalid position: " << x + 1 << ", " << y + 1 << std::endl;
    exit(EXIT_INV_POS);
  }
  if (v <= 0 || v > GRID_SIDE) {
    std::cerr << "Invalid value: " << v << std::endl;
    exit(EXIT_INV_VAL);
  }
  for (int i = 0; i < GRID_SIDE; ++i) {
    block_[x][i].forbid(v);
    block_[i][y].forbid(v);
  }
  for (int i = 0; i < 3; ++i)
    for (int j = 0; j < 3; ++j)
      block_[(x / 3) * 3 + x][(y / 3) * 3 + y].forbid(v);
}

void Grid::resolve()
{
  if (Grid::verbose)
    std::cout << "Resolving..." << std::endl;
}

void Grid::print() const
{
  int i, j, k;

  for (i = 0; i < GRID_SIDE; ++i) {
    print_line();
    if (i > 0 && i % 3 == 0)
      print_line();
    if (Grid::advprint) {
      for (int l = 0; l < 3; ++l) {
	for (j = 0; j < GRID_SIDE; ++j) {
	  if (j > 0 && j % 3 == 0)
	    std::cout << "| ";
	  std::cout << "|";
	  for (k = l * 3 + 1; k <= l * 3 + 3; ++k)
	    if (block_[i][j].value_get() == k)
	      std::cout << "\033[0;32m" << k  << "\033[0m";
	    else if (block_[i][j].is_forbid(k))
	      std::cout << "\033[0;31m" << k  << "\033[0m";
	    else
	      std::cout << k;
	}
	std::cout <<  "|" << std::endl;
      }
    }
    else {
      std::cout << "|";
      for (j = 0; j < GRID_SIDE; ++j) {
	if (j > 0 && j % 3 == 0) std::cout << " |";
	std::cout << " " << block_[i][j] << " |";
      }
      std::cout << std::endl;
    }
  }
  print_line();
}

bool Grid::is_done() const
{
  for (int i = 0; i < GRID_SIDE; ++i)
    for (int j = 0; j < GRID_SIDE; ++j)
      if (block_[i][j].value_get() == 0)
	return false;
  return true;
}

bool Grid::verify() const
{
  bool vertical_line[GRID_SIDE];
  bool horizontal_line[GRID_SIDE];
  int tmp;

  // check horizontals and verticales
  for (int i = 0; i < GRID_SIDE; ++i) {
    for (int j = 0; j < GRID_SIDE; ++j)
      horizontal_line[j] = vertical_line[j] = false;
    for (int j = 0; j < GRID_SIDE; ++j) {
      //horizontals
      tmp = block_[i][j].value_get() - 1;
      if (tmp < 0 || horizontal_line[tmp])
	return false;
      horizontal_line[tmp] = true;
      //verticals
      tmp = block_[j][i].value_get() - 1;
      if (tmp < 0 || vertical_line[tmp] == true)
	return false;
      vertical_line[tmp] = true;
    }
    for (int j = 0; j < GRID_SIDE; ++j)
      if (!vertical_line[j] || !horizontal_line[j])
	return false;
  }
  // check nine blocks (use vertical_block)
  for (int j = 0; j < GRID_SIDE; ++j)
    vertical_line[j] = false;
  for (int i = 0; i < GRID_SIDE; i += 3)
    for (int j = 0; j < GRID_SIDE; j += 3)
      for (int k = 0; k < 3; ++k)
	for (int l = 0; l < 3; ++l) {
	  tmp = block_[i + k][j + l].value_get() - 1;
	  if (tmp < 0 || vertical_line[tmp] == true)
	    return false;
	  vertical_line[tmp] = true;
	}
    for (int j = 0; j < GRID_SIDE; ++j)
      if (!vertical_line[j])
	return false;
    return true;
}
+1 −1

File changed and moved.

Contains only whitespace changes.

+24 −120
Original line number Diff line number Diff line
#include <stdlib.h>
#include "sudoku.hh"

bool Grid::verbose = false;

int main(int argc, char *argv[])
{
  int found;

  if (argc != 2 && argc !=3) {
    std::cerr << "Usage: sudoku [-v] file" << std::endl;
    return 1;
    return EXIT_USAGE;
  }
  if (argc == 3 && (argv[1] == "-v" || argv[2] == "-v"))
  if (argc == 3 && argv[1] == (std::string) "-v")
    Grid::verbose = true;
  if (argc == 3 && argv[1] == (std::string) "-p")
    Grid::advprint = true;
  Grid *grid = new Grid();
  grid->load(argv[Grid::verbose ? 1 : 2]);
  if (!grid->load(argv[Grid::verbose || Grid::advprint ? 2 : 1])) {
    std::cerr << "Loading failed !" << std::endl;
    return EXIT_LOADFAIL;
  }
  if (Grid::verbose) {
    std::cout << "Loaded grid:" << std::endl;
    grid->print();
  }
  grid->resolve();
  if (grid->verify()) {
  found = grid->verify() ? EXIT_FOUND : EXIT_NOTFOUND;
  if (found == EXIT_FOUND && Grid::verbose > 0)
    std::cout << "Solution found." << std::endl;
  grid->print();
  }
}

//
// GRID
//
int Grid::load(const char *filename)
{
  int val;
  std::fstream fs;

  std::cout << "coucou";
  try {
    fs.open(filename);
    std::cout << "sex";
  }
  catch (...) {
    std::cout << "sex";
  }
  std::cout << filename << std::endl;
  for (int i = 0; i < GRID_SIDE; ++i)
    for (int j = 0; j < GRID_SIDE; ++j) {
      fs >> std::dec >> val;
      std::cout << val << std::endl;
      //block_[i][j].set(val);
    }
  fs.close();
  return 0;
}

void Grid::resolve()
{
  
  return found;
}

void Grid::print() const
{
  int i, j;

  for (i = 0; i < GRID_SIDE; ++i) {
    //show first line
    for (j = 0; j < GRID_SIDE; j += 3)
      if (j == GRID_SIDE - 3) std::cout << " --- --- ---" << std::endl;
      else std::cout << " --- --- ---  ";
    //show nine group separator
    if (i > 0 && i % 3 == 0) {
      std::cout << std::endl;
      for (j = 0; j < GRID_SIDE; j += 3)
	if (j == GRID_SIDE - 3) std::cout << " --- --- ---" << std::endl;
	else std::cout << " --- --- ---  ";
    }
    std::cout << "|";
    for (j = 0; j < GRID_SIDE; ++j) {
      if (j > 0 && j % 3 == 0) std::cout << " |";
      std::cout << " " << block_[i][j].get() << " |";
    }
    std::cout << std::endl;
  }
  for (j = 0; j < GRID_SIDE; j += 3)
    if (j == GRID_SIDE - 3) std::cout << " --- --- ---" << std::endl;
    else std::cout << " --- --- ---  ";
}

bool Grid::is_done() const
{
  for (int i = 0; i < GRID_SIDE; ++i)
    for (int j = 0; j < GRID_SIDE; ++j)
      if (block_[i][j].get() == 0)
	return false;
  return true;
}

bool Grid::verify() const
{
  bool vertical_line[GRID_SIDE];
  bool horizontal_line[GRID_SIDE];
  int tmp;

  // check horizontals and verticales
  for (int i = 0; i < GRID_SIDE; ++i) {
    for (int j = 0; j < GRID_SIDE; ++j)
      horizontal_line[j] = vertical_line[j] = false;
    for (int j = 0; j < GRID_SIDE; ++j) {
      //horizontals
      tmp = block_[i][j].get() - 1;
      if (tmp < 0 || horizontal_line[tmp])
	return false;
      horizontal_line[tmp] = true;
      //verticals
      tmp = block_[j][i].get() - 1;
      if (tmp < 0 || vertical_line[tmp] == true)
	return false;
      vertical_line[tmp] = true;
    }
    for (int j = 0; j < GRID_SIDE; ++j)
      if (!vertical_line[j] || !horizontal_line[j])
	return false;
  }
  // check nine blocks (use vertical_block)
  for (int j = 0; j < GRID_SIDE; ++j)
    vertical_line[j] = false;
  for (int i = 0; i < GRID_SIDE; i += 3)
    for (int j = 0; j < GRID_SIDE; j += 3)
      for (int k = 0; k < 3; ++k)
	for (int l = 0; l < 3; ++l) {
	  tmp = block_[i + k][j + l].get() - 1;
	  if (tmp < 0 || vertical_line[tmp] == true)
	    return false;
	  vertical_line[tmp] = true;
	}
    for (int j = 0; j < GRID_SIDE; ++j)
      if (!vertical_line[j])
	return false;
    return true;
std::ostream &operator<<(std::ostream &stream, const Block &blk) {
  if (blk.value_ == 0)
    stream << " ";
  else
    stream << blk.value_;
  return stream;
}
+34 −5
Original line number Diff line number Diff line
@@ -2,13 +2,22 @@
#ifndef SUDOKU_HH_
# define SUDOKU_HH_

const int GRID_SIDE = 9; //must be able to divise 3

#include <cassert>
#include <ios>
#include <iostream>
#include <fstream>

const int GRID_SIDE = 9; //must be able to divise 3

enum {
  EXIT_FOUND = 0,
  EXIT_NOTFOUND = 1,
  EXIT_USAGE = 2,
  EXIT_LOADFAIL = 3,
  EXIT_INV_POS = 4,
  EXIT_INV_VAL = 5
};

class Block
{
public:
@@ -22,12 +31,19 @@ public:
    assert(value > 0 && value <= GRID_SIDE);
    return forbidden_[value];
  }
  int get() const { return value_; }
  int value_get() const { return value_; }
  bool is_forbid(int v) const {
    assert(v > 0 && v <= GRID_SIDE);
    return forbidden_[v - 1];
  }
  void init(int val) { assert(val >= 0 && val <= GRID_SIDE); value_ = val; }
  void set(int val) { assert(val > 0 && val <= GRID_SIDE); value_ = val; }
  void forbid(int val) {
    assert(val > 0 && val <= GRID_SIDE);
    if (val != value_)
      forbidden_[val] = true;
  }
  friend std::ostream &operator<<(std::ostream &stream, const Block &blk);
private:
  int value_;
  bool forbidden_[GRID_SIDE];
@@ -38,13 +54,26 @@ class Grid
public:
  int load(const char *filename);
  void print() const;
  inline void print_line() const;
  bool verify() const;
  bool is_done() const;
  void resolve();
  void pose(int x, int y, int v);
  static bool verbose;
  static bool advprint;
private:
 
  Block block_[GRID_SIDE][GRID_SIDE];
};

void Grid::print_line() const
{
  for (int j = 0; j < GRID_SIDE; ++j) {
    if (j % 3 == 0 && j > 0 && j < GRID_SIDE)
      std::cout << "  ";
    std::cout << " ---";
    if (j == GRID_SIDE - 1)
      std::cout << std::endl;
  }
}

#endif