Skip to content

Commit

Permalink
Parser and printer.
Browse files Browse the repository at this point in the history
  • Loading branch information
dlbeer committed May 24, 2012
0 parents commit c761344
Show file tree
Hide file tree
Showing 10 changed files with 1,296 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
cdok
.*.swp
*~
*.o
16 changes: 16 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
cdok -- Calcudoku solver/generator
Copyright (C) 2012 Daniel Beer <[email protected]>

Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all
copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
29 changes: 29 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# cdok -- Calcudoku solver/generator
# Copyright (C) 2012 Daniel Beer <[email protected]>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

CC ?= gcc
CDOK_CFLAGS = -O2 -Wall

all: cdok

cdok: main.o cdok.o parser.o printer.o
$(CC) -o $@ $^

clean:
rm -f cdok
rm -f *.o

%.o: %.c
$(CC) $(CFLAGS) $(CDOK_CFLAGS) -o $*.o -c $*.c
81 changes: 81 additions & 0 deletions cdok.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/* cdok -- Calcudoku solver/generator
* Copyright (C) 2012 Daniel Beer <[email protected]>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#include <string.h>

#include "cdok.h"

/* Map a character to a group ID */
uint8_t cdok_char_to_group(uint8_t ch)
{
if (ch >= 'A' && ch <= 'Z')
return ch - 'A';

if (ch >= 'a' && ch <= 'z')
return ch - 'a' + 26;

return CDOK_GROUP_NONE;
}

/* Map a group ID to a character */
uint8_t cdok_group_to_char(uint8_t g)
{
if (g < 26)
return g + 'A';

return g - 26 + 'a';
}

void cdok_init_puzzle(struct cdok_puzzle *puz, int size)
{
int i;

memset(puz, 0, sizeof(*puz));

for (i = 0; i < CDOK_GROUPS; i++)
puz->groups[i].target = -1;

puz->size = size;
memset(puz->group_map, CDOK_GROUP_NONE, sizeof(puz->group_map));
}

/* Flood fill from the src value to 0 on the given map. */
void cdok_flood_fill(uint8_t *map, uint8_t src, int x, int y)
{
int start_x = x;
int end_x = x;
int i;

if (map[CDOK_POS(x, y)] != src)
return;

while (start_x > 0 && map[CDOK_POS(start_x - 1, y)] == src)
start_x--;

while (end_x + 1 < CDOK_SIZE && map[CDOK_POS(end_x + 1, y)] == src)
end_x++;

for (i = start_x; i <= end_x; i++)
map[CDOK_POS(i, y)] = CDOK_GROUP_NONE;

if (y > 0)
for (i = start_x; i <= end_x; i++)
cdok_flood_fill(map, src, i, y - 1);

if (y + 1 < CDOK_SIZE)
for (i = start_x; i <= end_x; i++)
cdok_flood_fill(map, src, i, y + 1);
}
114 changes: 114 additions & 0 deletions cdok.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/* cdok -- Calcudoku solver/generator
* Copyright (C) 2012 Daniel Beer <[email protected]>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

#ifndef CDOK_H_
#define CDOK_H_

/* This header file defines basic data structures and utilities for
* representing puzzles and grids. A grid is represented using a flat
* array of size CDOK_CELLS. Coordinates are converted to and from
* array indices (cdok_pos_t) via the CDOK_POS* macros.
*/

#include <stdint.h>

/* Limits on puzzle and group sizes. */
#define CDOK_SIZE 16
#define CDOK_GROUPS 52
#define CDOK_CELLS 256
#define CDOK_GROUP_SIZE 8

/* Position reference. This is an index into a grid. */
typedef int cdok_pos_t;

#define CDOK_POS(x, y) (((y) << 4) | (x))
#define CDOK_POS_X(c) ((c) & 0xf)
#define CDOK_POS_Y(c) ((c) >> 4)

/* Group types. */
typedef enum {
CDOK_SUM = '+',
CDOK_DIFFERENCE = '-',
CDOK_PRODUCT = '*',
CDOK_RATIO = '/'
} cdok_gtype_t;

/* Clue group. This consists of a type, clue value (target), and a list
* of member cells, specified as position references.
*
* A size of 0 indicates that the group is unused/unallocated.
*/
struct cdok_group {
cdok_gtype_t type;
int target;
unsigned int size;
cdok_pos_t members[CDOK_GROUP_SIZE];
};

#define CDOK_GROUP_NONE 0xff

/* Puzzle representation. This consists of:
*
* size: the dimensions of the puzzle (<= CDOK_SIZE)
* values: given clues, indexed by cdok_pos_t. A value of zero
* indicates that there is no given value for this cell.
* groups: a list of grouped cells and their clues.
* group_map: a mapping from cells to the groups to which they belong,
* if any (indexed by cdok_pos_t). A value of CDOK_GROUP_NONE
* indicates that the cell does not belong to a group.
*
* The following basic invariants should hold:
*
* * 1 <= size <= CDOK_SIZE
* * The size of any valid group is >= 2.
* * If group_map[c] == g for every cell c in group g.
* * Cells are a member of one group only, at most.
* * Groups are composed of contiguous cells -- you can trace a route
* from any cell in a group to any other, travelling only
* up/down/left/right.
*/
struct cdok_puzzle {
unsigned int size;
struct cdok_group groups[CDOK_GROUPS];
uint8_t values[CDOK_CELLS];
uint8_t group_map[CDOK_CELLS];
};

/* This data type is used to represent sets of values. It's guaranteed
* to have at least CDOK_SIZE bits.
*/
typedef uint16_t cdok_set_t;

#define CDOK_SET_SINGLE(c) (1 << ((c) - 1))
#define CDOK_SET_ONES(s) ((1 << (s)) - 1)
#define CDOK_SET_RANGE(min, max) \
(CDOK_SET_ONES(max - min + 1) << (min - 1))

/* Initialize a new, empty grid */
void cdok_init_puzzle(struct cdok_puzzle *puz, int size);

/* Flood-fill a group map, setting cells from the source value to
* CDOK_GROUP_NONE. This function is used to check for valid geometry.
*/
void cdok_flood_fill(uint8_t *map, uint8_t src, int x, int y);

/* Each group is named in a puzzle spec using an alphabetic character.
* These functions map group indices to and from characters.
*/
uint8_t cdok_group_to_char(uint8_t g);
uint8_t cdok_char_to_group(uint8_t ch);

#endif
Loading

0 comments on commit c761344

Please sign in to comment.