Example #1
0
// FetchWebSudoku scrapes a sudoku puzzle from websudoku.com.
// A Sudoku is returned on success, nil otherwise.
func FetchWebSudoku(level, id int) *common.Sudoku {
	resp, err := http.PostForm(webSudokuEndpoint,
		url.Values{"level": {strconv.Itoa(level)}, "set_id": {strconv.Itoa(id)}})

	if err != nil {
		return nil
	}

	defer resp.Body.Close()
	parsed, perr := html.Parse(resp.Body)

	if perr != nil {
		return nil
	}

	cheat, editMask := scrapeCheatAndEditMask(parsed)

	if cheat == nil || editMask == nil {
		return nil
	}

	if len(*cheat) != 81 || len(*editMask) != 81 {
		return nil
	}

	sudoku := common.NewSudoku(3)
	for i := 0; i < 81; i++ {
		if (*editMask)[i] == '0' {
			sudoku.Values[i/9][i%9] = int((*cheat)[i]) - int('0')
		}
	}

	return sudoku
}
Example #2
0
// Next deserializes and returns the next puzzle in the stream.
// On success, a Sudoku is returned without an error. On failure,
// an error is returned without a Sudoku and all subsequent calls
// return the same error. If the Reader has reached the end of the
// stream, Next returns nil, nil.
func (r *Reader) Next() (*common.Sudoku, error) {
	// once a terminal state is reached, subsequent calls return the terminal state
	if r.termOk {
		return nil, nil
	}
	if r.termErr != nil {
		return nil, r.termErr
	}

	// attempt to read the next puzzle
	r.curSudoku = nil
	r.curSudokuRow = 0

	eof, size, err := r.scanSize()
	if eof {
		r.termOk = true
		return nil, nil
	}
	if err != nil {
		r.termErr = err
		return nil, err
	}

	r.curSudoku = common.NewSudoku(uint8(size))
	for s := r.curSudoku.Size * r.curSudoku.Size; s > 0; s-- {
		eof, err := r.scanRow()
		if eof {
			r.termOk = true
			return nil, nil
		}
		if err != nil {
			r.termErr = err
			return nil, err
		}
	}
	return r.curSudoku, nil
}