Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # This is a shell archive. Save it in a file, remove anything before
- # this line, and then unpack it by entering "sh file". Note, it may
- # create directories; files and directories will be owned by you and
- # have default permissions.
- #
- # This archive contains:
- #
- # 2025-10-26.json
- # create-puzzle-header.pl
- # get-puzzle-from-json.pl
- # Makefile
- # pips.c
- # README
- # remove-fixed.pl
- #
- echo x - 2025-10-26.json
- sed 's/^X//' >2025-10-26.json << 'f236fa34ab2378ed9dd359e6a772e319'
- X{"printDate":"2025-10-26","editor":"Ian Livengood","easy":{"id":57,"backendId":"e688601b48895efeb7f2872eeac9c778","constructors":"Heidi Erwin","dominoes":[[6,6],[5,5],[5,2],[6,1]],"regions":[{"indices":[[0,0],[0,1]],"type":"greater","target":7},{"indices":[[0,3],[1,3]],"type":"equals"},{"indices":[[1,0],[1,1],[1,2]],"type":"sum","target":17},{"indices":[[2,2]],"type":"empty"}],"solution":[[[0,1],[1,1]],[[0,3],[1,3]],[[1,0],[0,0]],[[1,2],[2,2]]]},"medium":{"id":51,"backendId":"2340fa8497925b17832d0ae1c3bb5d8e","constructors":"Rodolfo Kurchan","dominoes":[[2,4],[0,4],[4,6],[1,4],[0,0],[1,2],[0,2],[5,6],[5,4],[1,3],[0,5],[5,5],[1,1]],"regions":[{"indices":[[0,3]],"type":"empty"},{"indices":[[1,2],[1,3],[1,4]],"type":"unequal"},{"indices":[[2,2],[2,3]],"type":"sum","target":0},{"indices":[[2,4]],"type":"sum","target":1},{"indices":[[3,3]],"type":"sum","target":2},{"indices":[[4,0],[4,1],[5,1]],"type":"equals"},{"indices":[[4,2]],"type":"sum","target":3},{"indices":[[4,3],[4,4],[4,5],[4,6]],"type":"equals"},{"indices":[[4,7]],"type":"empty"},{"indices":[[5,2],[6,2]],"type":"sum","target":10},{"indices":[[5,3],[5,4],[6,3],[6,4]],"type":"sum","target":22},{"indices":[[5,5],[6,5]],"type":"unequal"},{"indices":[[5,6]],"type":"empty"}],"solution":[[[5,5],[5,6]],[[2,2],[1,2]],[[6,5],[6,4]],[[4,6],[4,7]],[[4,0],[4,1]],[[2,4],[1,4]],[[2,3],[3,3]],[[6,2],[6,3]],[[1,3],[0,3]],[[4,3],[4,2]],[[5,1],[5,2]],[[5,3],[5,4]],[[4,4],[4,5]]]},"hard":{"id":94,"backendId":"02ac54ef6ffe55679572dac5b145d002","constructors":"Heidi Erwin","dominoes":[[5,1],[3,1],[1,1],[4,2],[0,4],[4,4],[5,3],[0,2]],"regions":[{"indices":[[0,0],[0,1],[0,2]],"type":"equals"},{"indices":[[1,0],[1,1],[2,0],[2,1]],"type":"sum","target":5},{"indices":[[1,2],[2,2]],"type":"sum","target":1},{"indices":[[2,3]],"type":"empty"},{"indices":[[3,0],[4,0]],"type":"equals"},{"indices":[[3,1],[3,2]],"type":"sum","target":3},{"indices":[[4,1],[4,2]],"type":"sum","target":5}],"solution":[[[3,0],[2,0]],[[3,1],[2,1]],[[1,1],[1,2]],[[0,0],[1,0]],[[2,2],[2,3]],[[0,1],[0,2]],[[4,0],[4,1]],[[3,2],[4,2]]]}}
- X
- f236fa34ab2378ed9dd359e6a772e319
- echo x - create-puzzle-header.pl
- sed 's/^X//' >create-puzzle-header.pl << '462d9a1a9f0c053b0519af07720f78e7'
- X#!/usr/bin/env perl
- Xuse strict;
- Xuse Data::Dumper;
- X$Data::Dumper::Sortkeys = 1;
- X
- Xmy @link; # [square, neighbor]
- Xmy @tile; # [faceA, faceB]
- Xmy @constraint; # [rule, [sq, ...]]
- Xmy %coords; # sq => [row, col]
- X
- Xmy %constraint_map; # square => constraint
- Xmy @constraint_name;
- Xmy %constraint_rule; # name => [rule, [squares]]
- X
- Xmy $num_rows = 0;
- Xmy $num_cols = 0;
- X
- Xmain();
- X
- Xsub main
- X{
- X print "/***************************\\\n";
- X print "| |\n";
- X print "| THIS IS A GENERATED FILE! |\n";
- X print "| DO NOT EDIT! |\n";
- X print "| |\n";
- X print "\\***************************/\n";
- X read_spec();
- X make_constraints();
- X make_board();
- X make_tiles();
- X}
- X
- Xsub make_constraints()
- X{
- X print "int c_none();\n";
- X foreach (@constraint) {
- X my $rule = $_->[0];
- X my @squares = @{$_->[1]};
- X my $name = "c_" . join("_", @squares);
- X push @constraint_name, $name;
- X $constraint_rule{$name} = $_;
- X foreach my $sq (@squares) {
- X $constraint_map{$sq} = $name;
- X }
- X print "int $name();\n";
- X }
- X}
- X
- Xsub make_tiles()
- X{
- X my $num_tiles = @tile;
- X
- X print "Tile tiles[$num_tiles] = {\n";
- X foreach (@tile) {
- X my($left, $right) = @$_;
- X print " {$left, $right, -1, -1},\n";
- X }
- X print "};\n";
- X}
- X
- Xsub make_board()
- X{
- X print "Group_Base group_base[] = {\n";
- X foreach (@constraint) {
- X my($rule, $squares) = @$_;
- X my $sq = $squares->[@$squares-1];
- X my $r = pad($coords{$sq}[0]);
- X my $c = pad($coords{$sq}[1]);
- X
- X print " {\"$rule\", $r, $c},\n";
- X }
- X print "};\n";
- X
- X my %neighbor;
- X foreach (@link) {
- X my($a, $b) = @$_;
- X push @{$neighbor{$a}}, $b;
- X push @{$neighbor{$b}}, $a;
- X }
- X
- X my @squares = sort {$a<=>$b} keys %neighbor;
- X print "Square board[", scalar(@squares), "] = {\n";
- X my $i = 0;
- X foreach (@squares) {
- X my @adjacent = @{$neighbor{$_}};
- X sort {$a<=>$b} @adjacent;
- X push @adjacent, -1 while @adjacent < 4;
- X my $constraint = $constraint_map{$_} || "c_none";
- X my $r = pad($coords{$_}[0]);
- X my $c = pad($coords{$_}[1]);
- X my $gu = $coords{$_}[2];
- X my $g = '"' . $gu . '"';
- X my $pi = pad($i, 2);
- X my $nl = join(", ", map {pad($_,2)} @adjacent);
- X print "/*$pi*/ {$r, $c, -1, $g, {$nl}, $constraint},\n";
- X ++$i;
- X }
- X print "};\n";
- X
- X print "#define ROWS $num_rows\n";
- X print "#define COLS $num_cols\n";
- X foreach (@squares) {
- X print "#define SQ$_ board[$_].pips\n";
- X }
- X
- X print "int c_none()\n";
- X print "{\n";
- X print " return 1;\n";
- X print "}\n";
- X foreach (@constraint_name) {
- X my($rule, $sq) = @{$constraint_rule{$_}};
- X print "int $_()\n";
- X print "{\n";
- X
- X if ($rule =~ m{(^\d+)}) {
- X my $goal = $1;
- X my $t = test_not_full($sq);
- X print " if ($t) return 1;\n";
- X my $t = sum_squares($sq);
- X print " if ($t == $goal) return 1;\n";
- X print " else return 0;\n"
- X } elsif ($rule eq "=") {
- X my $t = test_not_full($sq);
- X print " if ($t) return 1;\n";
- X my $t = test_equal($sq);
- X print " if ($t) return 1;\n";
- X print " else return 0;\n";
- X } elsif ($rule =~ m{^([<>])(\d+)}) {
- X my($op,$goal) = ($1, $2);
- X my $t = test_not_full($sq);
- X print " if ($t) return 1;\n";
- X my $t = sum_squares($sq);
- X print " if ($t $op $goal) return 1;\n";
- X print " else return 0;\n"
- X } elsif ($rule eq "<>") {
- X print " int mask = 0;\n";
- X my $t = test_not_full($sq);
- X print " if ($t) return 1;\n";
- X foreach (@$sq) {
- X print " if (mask & (1<<SQ$_)) return 0;\n";
- X print " mask |= 1 << SQ$_;\n";
- X }
- X print " return 1;\n";
- X } else {
- X print "$_: <$rule> on ", join(", ", @$sq), "\n";
- X }
- X print "}\n";
- X }
- X}
- X
- Xsub test_not_full
- X{
- X my($sq) = @_;
- X return join(" || ", map{qq{SQ$_ == -1}} @$sq);
- X}
- X
- Xsub sum_squares
- X{
- X my($sq) = @_;
- X return join(" + ", map{qq{SQ$_}} @$sq);
- X}
- X
- Xsub test_equal
- X{
- X my($sq) = @_;
- X my @sq = @$sq;
- X my $target = "SQ" . shift @sq;
- X
- X return join(" && ", map{qq{$target == SQ$_}} @sq);
- X}
- X
- Xsub read_spec
- X{
- X my @b_lines;
- X my @c_lines;
- X my @d_lines;
- X my $width = 0;
- X my %constraints; # name => [rule, [squares]]
- X while (<>) {
- X chomp;
- X #if (m{^[a-zA-Z]\s+}) { push @c_lines, $_; }
- X if (m{^[a-zA-Z\[\\\]\^]\s+}) { push @c_lines, $_; }
- X elsif (m{^\d+(\s+\d+)*}) { push @d_lines, $_; }
- X elsif (m{[-.a-zA-Z]+}) {
- X push @b_lines, $_;
- X $width = length($_) if length($_) > $width;
- X }
- X }
- X
- X # initial constraints table with names and rules
- X foreach (@c_lines) {
- X my($name, $rule) = $_ =~ m{^([a-zA-Z])\s+(\S+)};
- X $constraints{$name} = [$rule, []];
- X }
- X
- X # build map of board and add squares to constraints
- X my $next_square = 0;
- X my @b_fixed;
- X my $r = 0;
- X my $c = 0;
- X $num_rows = scalar(@b_lines);
- X foreach (@b_lines) {
- X my @row = split //, $_;
- X push @row, '.' while @row < $width;
- X foreach my $s (@row) {
- X if ($s eq '-') {
- X $coords{$next_square} = [$r, $c, ' '];
- X $s = $next_square++;
- X } elsif ($s =~ /([a-zA-Z])/) {
- X push @{$constraints{$1}[1]}, $next_square;
- X $coords{$next_square} = [$r, $c, $1];
- X $s = $next_square++;
- X }
- X ++$c;
- X $num_cols = $c if $c > $num_cols;
- X }
- X push @b_fixed, \@row;
- X $c = 0;
- X ++$r;
- X }
- X
- X # print links
- X for (my $r = 0; $r < $num_rows; ++$r) {
- X for (my $c = 0; $c < $width; ++$c) {
- X my $sq = $b_fixed[$r][$c];
- X if ($sq ne '.') {
- X my $ad = $c + 1 < $width ? $b_fixed[$r][$c+1] : '.';
- X push @link, [$sq, $ad] if $ad != '.';
- X $ad = $r + 1 < $num_rows ? $b_fixed[$r+1][$c] : '.';
- X push @link, [$sq, $ad] if $ad != '.';
- X }
- X }
- X }
- X
- X foreach (sort {$a cmp $b} keys %constraints) {
- X my($rule, $list) = @{$constraints{$_}};
- X #print "$rule: ", join(' ', @$list), "\n";
- X push @constraint, [$rule, [@$list]];
- X }
- X
- X foreach (@d_lines) {
- X my @d = split /\s+/, $_;
- X foreach (@d) {
- X my($a, $b) = split //, $_;
- X push @tile, [$a, $b];
- X }
- X }
- X
- X #foreach (sort {$a<=>$b} keys %coords) {
- X # print "$_\t", join(" ", @{$coords{$_}}), "\n";
- X #}
- X foreach (@b_fixed) {
- X print '// ', join(' ', map {pad($_,2)} @$_), "\n\n";
- X }
- X}
- X
- Xsub pad
- X{
- X my($str, $w) = @_;
- X $str = ' ' . $str while length($str) < $w;
- X return $str;
- X}
- 462d9a1a9f0c053b0519af07720f78e7
- echo x - get-puzzle-from-json.pl
- sed 's/^X//' >get-puzzle-from-json.pl << '05c4bfc6519858489c47fcf2e07b8f3e'
- X#!/usr/bin/env perl
- Xuse strict;
- Xuse JSON;
- Xuse Data::Dumper;
- X$Data::Dumper::Sortkeys = 1;
- X
- X# You can find the puzzle for YYYY-MM-DD at
- X# https://www.nytimes.com/svc/pips/v1/YYYY-MM-DD.json
- X
- Xmain();
- X
- Xsub main
- X{
- X my $which = shift @ARGV || die "Difficulty not given\n";
- X my $json_in;
- X while (<>) {
- X $json_in .= $_;
- X }
- X my $p = decode_json $json_in;
- X #print Dumper($p);
- X
- X #my $date = $p->{printDate};
- X
- X my $e = make_encoding($p->{$which});
- X}
- X
- Xsub make_encoding
- X{
- X my($p) = @_;
- X
- X my %board;
- X my %constraint;
- X my $next_label = 'A';
- X
- X print join(' ', map {join('', @$_)} @{$p->{dominoes}}), "\n\n";
- X
- X foreach (@{$p->{regions}}) {
- X my $type = $_->{type};
- X my $target = $_->{target};
- X
- X my $label;
- X if ($type eq 'empty') {
- X $label = '-';
- X } else {
- X if ($next_label eq '[') { $next_label = 'a'; }
- X $label = $next_label;
- X $next_label = chr(1 + ord($next_label));
- X if ($type eq "sum") { $constraint{$label} = $target; }
- X elsif ($type eq "less") { $constraint{$label} = "<$target"; }
- X elsif ($type eq "greater") { $constraint{$label} = ">$target"; }
- X elsif ($type eq "equals") { $constraint{$label} = "="; }
- X elsif ($type eq "unequal") { $constraint{$label} = "<>"; }
- X else { die "Unrecognize constrain $type:[$target]\n"; }
- X }
- X
- X foreach (@{$_->{indices}}) {
- X my($row, $col) = ($_->[0], $_->[1]);
- X $board{$row}{$col} = $label;
- X }
- X }
- X
- X foreach (sort {$a cmp $b} keys %constraint) {
- X print "$_ ", $constraint{$_}, "\n";
- X }
- X print "\n";
- X
- X my $write_row = 0;
- X foreach my $row (sort {$a<=>$b} keys %board) {
- X while ($write_row < $row) {
- X print ".\n";
- X ++$write_row;
- X }
- X my $write_col = 0;
- X foreach my $col (sort {$a<=>$b} keys %{$board{$row}}) {
- X while ($write_col < $col) {
- X print '.';
- X ++$write_col;
- X }
- X print $board{$row}{$col};
- X ++$write_col;
- X }
- X print "\n";
- X ++$write_row;
- X }
- X}
- 05c4bfc6519858489c47fcf2e07b8f3e
- echo x - Makefile
- sed 's/^X//' >Makefile << '60f8520832b6f80996c175fbf41f4e55'
- X#vim: set tabstop=8 noexpandtab:
- Xsolve: pips.c puzzle.h
- X cc -O3 pips.c -o solve
- X
- Xclean:
- X rm solve puzzle.h
- X
- X
- 60f8520832b6f80996c175fbf41f4e55
- echo x - pips.c
- sed 's/^X//' >pips.c << 'e72e2e6d8eef828fea6eb57b7863cb90'
- X#include <stdio.h>
- X#include <stdlib.h>
- X#include <string.h>
- X#include <iconv.h>
- X#include <wchar.h>
- X#include <errno.h>
- X
- X#define SHOW 1
- X#define CLEAR 0
- X#define LABELS 0
- X
- Xint opt_show = SHOW;
- Xint opt_clear = CLEAR;
- Xint opt_labels = LABELS;
- X
- Xtypedef struct {
- X int y; /* row */
- X int x; /* col */
- X int pips; /* -1 if empty, # of pips if not empty */
- X char * group; /* name of group */
- X int neighbors[4];
- X int (*constraint)();
- X} Square;
- X
- Xtypedef struct {
- X int nA; /* # of pips on A end */
- X int nB; /* # of pips on B end */
- X int sA; /* where A end is placed (-1 if not placed) */
- X int sB; /* where B end is placed (-1 if not placed) */
- X} Tile;
- X
- Xtypedef struct {
- X char * group;
- X int y;
- X int x;
- X} Group_Base;
- X
- Xchar *** rows = 0;
- Xint solution_count = 0;
- X
- X#include "puzzle.h"
- X
- Xvoid show_tiles_graphic(void);
- Xvoid show_tiles_text(void);
- Xint place(char * lp, char * cp, int pos);
- Xvoid solve(int depth);
- Xvoid draw_square(int y, int x, int pips, int up);
- Xvoid erase_line(int py, int px, int dy, int dx, int n, char * what);
- Xvoid draw_tile(int y, int x, int pips1, int pips2,
- X char * g1, char * g2, int dir);
- Xvoid label_square(int y, int x, char * label);
- X
- X
- Xint main(int argc, char *argv[]) {
- X for (int i = 1; i < argc; ++i) {
- X if (strcmp(argv[i], "-c") == 0) { opt_clear = 1; }
- X if (strcmp(argv[i], "-l") == 0) { opt_labels = 1; }
- X if (strcmp(argv[i], "-q") == 0) { opt_show = 0; }
- X }
- X solve(0);
- X printf("Solutions: %d\n", solution_count);
- X return 0;
- X}
- X
- X#define TL "┌"
- X#define TR "┐"
- X#define BL "└"
- X#define BR "┘"
- X#define TT "┬"
- X#define BT "┴"
- X#define LT "├"
- X#define RT "┤"
- X#define HL "─"
- X#define VL "│"
- X#define CC "┼"
- X#define PIP "◎";
- X
- X#define SQ_X 7
- X#define SQ_Y 3
- X
- X#define PIX_X ((SQ_X+1)*COLS+1)
- X#define PIX_Y ((SQ_Y+1)*ROWS+1)
- X
- X#define PX 2
- X#define PY 1
- X
- Xvoid show_tiles_text(void)
- X{
- X char * sep = "";
- X for (int t = 0; t < sizeof tiles / sizeof(Tile); ++t) {
- X printf("%s%d/%d(%d,%d)", sep, tiles[t].nA, tiles[t].nB,
- X tiles[t].sA, tiles[t].sB);
- X sep = " ";
- X }
- X printf("\n");
- X}
- X
- Xvoid show_tiles_graphic(void)
- X{
- X static int inited = 0;
- X printf("board is %d rows x %d cols\n", PIX_Y, PIX_X);
- X if (! inited) rows = (char ***)malloc(PIX_Y * sizeof(char *));
- X for (int i = 0; i < PIX_Y; ++i) {
- X char ** line = inited ? rows[i] : (char **)malloc(PIX_X * sizeof(char *));
- X for (int j = 0; j < PIX_X; ++j) {
- X line[j] = " ";
- X }
- X rows[i] = line;
- X }
- X inited = 1;
- X
- X for (int t = 0; t < sizeof tiles / sizeof(Tile); ++t) {
- X int dir = 0;
- X int rA = board[tiles[t].sA].y;
- X int cA = board[tiles[t].sA].x;
- X int nA = tiles[t].nA;
- X char * gA = board[tiles[t].sA].group;
- X int rB = board[tiles[t].sB].y;
- X int cB = board[tiles[t].sB].x;
- X int nB = tiles[t].nB;
- X char * gB = board[tiles[t].sB].group;
- X
- X if (rA > rB) dir = 0;
- X else if (rA < rB) dir = 2;
- X else if (cA < cB) dir = 3;
- X else dir = 1;
- X
- X draw_tile(rA, cA, nA, nB, gA, gB, dir);
- X }
- X if (opt_labels) {
- X for (int i = 0; i < sizeof group_base / sizeof(group_base[0]); ++i) {
- X label_square(group_base[i].y, group_base[i].x, group_base[i].group);
- X }
- X }
- X
- X for (int i = 0; i < PIX_Y; ++i) {
- X for (int j = 0; j < PIX_X; ++j) {
- X printf("%s", rows[i][j]);
- X }
- X putchar('\n');
- X }
- X putchar('\n');
- X if (opt_clear) {
- X exit(0);
- X }
- X}
- X
- Xvoid label_square(int y, int x, char * label)
- X{
- X int px = 1 + x * (SQ_X + 1);
- X int py = 1 + y * (SQ_Y + 1);
- X int n = strlen(label);
- X if (n == 1) {
- X rows[py + SQ_Y][px + SQ_X] = label;
- X } else {
- X for (int i = 0; i < n; ++i) {
- X char * one = (char *)malloc(2); //TODO: when does this get freed?
- X one[0] = label[i];
- X one[1] = '\0';
- X rows[py + SQ_Y][px + SQ_X + i] = one;
- X }
- X }
- X}
- X
- X/* dir: 0 == up, 1 == left, 2 == down, 3 == right */
- Xvoid draw_tile(int y, int x, int pips1, int pips2,
- X char * g1, char * g2, int dir)
- X{
- X if (opt_clear) {
- X pips1 = pips2 = 0;
- X }
- X char * what = (strcmp(g1, g2) == 0) ? " " : ".";
- X int px = 1 + x * (SQ_X + 1);
- X int py = 1 + y * (SQ_Y + 1);
- X draw_square(y, x, pips1, (dir == 0 || dir == 2) ? 1 : 0);
- X
- X switch (dir) {
- X case 0: --y; break;
- X case 1: --x; break;
- X case 2: ++y; break;
- X case 3: ++x; break;
- X }
- X
- X int px2 = 1 + x * (SQ_X + 1);
- X int py2 = 1 + y * (SQ_Y + 1);
- X draw_square(y, x, pips2, (dir == 0 || dir == 2) ? 1 : 0);
- X
- X switch (dir) {
- X case 0:
- X erase_line(py-1, px, 0, 1, 7, what);
- X break;
- X case 1:
- X erase_line(py, px-1, 1, 0, 3, what);
- X break;
- X case 2:
- X erase_line(py2-1, px, 0, 1, 7, what);
- X break;
- X case 3:
- X erase_line(py2, px2-1, 1, 0, 3, what);
- X break;
- X }
- X}
- X
- Xvoid erase_line(int py, int px, int dy, int dx, int n, char * what)
- X{
- X if (! opt_clear) {
- X while (n-- > 0) {
- X if (px > 0 && py > 0)
- X rows[py][px] = what;
- X else {
- X printf("Internal error: out of bounds\n");
- X exit(1);
- X }
- X py += dy;
- X px += dx;
- X }
- X }
- X}
- X
- Xvoid draw_square(int y, int x, int pips, int up)
- X{
- X int i, j;
- X x = 1 + x * (SQ_X + 1);
- X y = 1 + y * (SQ_Y + 1);
- X for (i = y; i < y+SQ_Y; ++i)
- X for (j = x; j < x+SQ_X; ++j)
- X rows[i][j] = " ";
- X
- X // frame top and bottom
- X for (j = x; j < x+SQ_X; ++j) {
- X rows[y-1][j] = HL;
- X rows[y+SQ_Y][j] = HL;
- X }
- X // frame the sides
- X for (i = y; i < y+SQ_Y; ++i) {
- X rows[i][x-1] = VL;
- X rows[i][x+SQ_X] = VL;
- X }
- X // corners
- X rows[y-1][x-1] = TL;
- X rows[y+SQ_Y][x-1] = BL;
- X rows[y+SQ_Y][x+SQ_X] = BR;
- X rows[y-1][x+SQ_X] = TR;
- X
- X x += 1;
- X switch (pips) {
- X case 1:
- X rows[y+PY][x+PX] = PIP;
- X break;
- X case 2:
- X if (up) {
- X rows[y][x] = PIP;
- X rows[y+2*PY][x+2*PX] = PIP;
- X } else {
- X rows[y][x+2*PX] = PIP;
- X rows[y+2*PY][x] = PIP;
- X }
- X break;
- X case 3:
- X rows[y+PY][x+PX] = PIP;
- X if (up) {
- X rows[y][x] = PIP;
- X rows[y+2*PY][x+2*PX] = PIP;
- X } else {
- X rows[y][x+2*PX] = PIP;
- X rows[y+2*PY][x] = PIP;
- X }
- X break;
- X case 4:
- X rows[y][x] = PIP;
- X rows[y+2*PY][x] = PIP;
- X rows[y][x+2*PX] = PIP;
- X rows[y+2*PY][x+2*PX] = PIP;
- X break;
- X case 5:
- X rows[y+PY][x+PX] = PIP;
- X rows[y][x] = PIP;
- X rows[y+2*PY][x] = PIP;
- X rows[y][x+2*PX] = PIP;
- X rows[y+2*PY][x+2*PX] = PIP;
- X break;
- X case 6:
- X if (up) {
- X rows[y][x] = PIP;
- X rows[y+PY][x] = PIP;
- X rows[y+2*PY][x] = PIP;
- X rows[y][x+2*PX] = PIP;
- X rows[y+PY][x+2*PX] = PIP;
- X rows[y+2*PY][x+2*PX] = PIP;
- X } else {
- X rows[y][x] = PIP;
- X rows[y][x+PX] = PIP;
- X rows[y][x+2*PX] = PIP;
- X rows[y+2*PY][x] = PIP;
- X rows[y+2*PY][x+PX] = PIP;
- X rows[y+2*PY][x+2*PX] = PIP;
- X }
- X break;
- X }
- X}
- X
- Xvoid indent(int depth)
- X{
- X if (depth > 0) {
- X for (int i = 0; i < 2*depth; ++i) putchar('_');
- X }
- X}
- X
- Xvoid solve(int depth)
- X{
- X int sq;
- X int i;
- X int t;
- X
- X
- X /* find an empty square */
- X sq = sizeof board / sizeof(Square);
- X while (--sq >= 0) {
- X if (board[sq].pips == -1) break;
- X }
- X if ( sq < 0) {
- X ++solution_count;
- X if (opt_show) {
- X show_tiles_graphic();
- X show_tiles_text();
- X }
- X return;
- X }
- X
- X for (i = 0; i < 4; ++i) {
- X int ad = board[sq].neighbors[i];
- X if (ad >= 0 && board[ad].pips == -1) {
- X for (t = 0; t < sizeof tiles / sizeof(Tile); ++t) {
- X if (tiles[t].sA != -1) continue;
- X board[sq].pips = tiles[t].nA;
- X board[ad].pips = tiles[t].nB;
- X tiles[t].sA = sq;
- X tiles[t].sB = ad;
- X //indent(depth); printf("Try %d%d on %d/%d\n", board[sq].pips, board[ad].pips, sq, ad);
- X if ((*board[sq].constraint)() && (*board[ad].constraint)()) {
- X solve(depth+1);
- X }
- X if (tiles[t].nA != tiles[t].nB) {
- X board[sq].pips = tiles[t].nB;
- X board[ad].pips = tiles[t].nA;
- X tiles[t].sB = sq;
- X tiles[t].sA = ad;
- X //indent(depth); printf("Try %d%d on %d/%d\n", board[sq].pips, board[ad].pips, sq, ad);
- X if ((*board[sq].constraint)() && (*board[ad].constraint)()) {
- X solve(depth+1);
- X }
- X }
- X board[sq].pips = -1;
- X board[ad].pips = -1;
- X tiles[t].sA = -1;
- X tiles[t].sB = -1;
- X }
- X }
- X }
- X}
- e72e2e6d8eef828fea6eb57b7863cb90
- echo x - README
- sed 's/^X//' >README << '0ee3a4adc07a27bcc83b176e68e8893f'
- XTo use this Pips solver, first obtain the JSON file from the NYT for
- Xthe day the puzzle was published. I've included the file for the
- X2025-10-26 puzzles to get you started. There's a comment in
- Xget-puzzle-from-json.pl telling where to get other days.
- X
- XTo solve the puzzle use get-puzzle-from-json.pl to extract the
- Xparticular difficulty level you are interested in from the JSON
- Xfile, like this:
- X
- X ./get-puzzle-from-json.pl easy < 2025-10-26.json
- X
- XThat will extract that particular puzzle and convert it to
- Xan intermediate format which will be printed on stdout.
- XRedirect stdout to some temp file for use in the next step,
- Xor simply pipe the output to the program in the next step.
- X
- XThe script create-puzzle-header.pl turns that intermediate
- Xformat into a C header file the solver can use. Run it on
- Xthe output of get-puzzle-from-json.pl and save the output
- Xas puzzle.h.
- X
- XCompile the solver with
- X
- X cc -O3 pips.c -o solve
- X
- Xor if you use make a Makefile is included for this.
- X
- XThen run solve and it will shows you the solutions.
- X
- XThere are three flags you can give solve.
- X
- X-l Add the constraint labels. This is pretty useless right now
- Xbecause the output doesn't show the region boundaries.
- X
- X-c Don't show tiles. Just show the shape of the puzzle.
- X
- X-q Don't show the solutions. It will just show you how many there
- Xare.
- X
- XNOTE! When you change puzzles don't forget to recompile after
- Xyou make the new puzzle.h.
- X
- XThere's one more script included: remove-fixed.pl. When a puzzle
- Xhas multiple solutions you can do this:
- X
- X ./solve | grep / | ./remove-fixed.pl
- X
- Xand it gives you a list of all the tiles, and for each shows
- Xall the different places it can appear. The locations are given
- Xusing square numbers. Near the top of puzzle.h is a diagram
- Xshowing the square number assignments.
- 0ee3a4adc07a27bcc83b176e68e8893f
- echo x - remove-fixed.pl
- sed 's/^X//' >remove-fixed.pl << 'a58dd082170b431a26ad571650597d60'
- X#!/usr/bin/env perl
- Xuse strict;
- Xuse Data::Dumper;
- X$Data::Dumper::Sortkeys = 1;
- X
- Xmy %cover;
- X
- Xmain();
- X
- Xsub main
- X{
- X while (<>) {
- X chomp;
- X foreach (split /\s+/, $_) {
- X my($tile, $loc) = $_ =~
- X m{(\d.\d).(\d+,\d+)};
- X $cover{$tile}{"($loc)"} = 1
- X }
- X }
- X foreach my $tile (sort {$a cmp $b} keys %cover) {
- X my @squares = sort {$a cmp $b} keys %{$cover{$tile}};
- X print "$tile: ", join(" ", @squares), "\n";
- X }
- X}
- a58dd082170b431a26ad571650597d60
- chmod +x create-puzzle-header.pl get-puzzle-from-json.pl remove-fixed.pl
- exit
Advertisement
Add Comment
Please, Sign In to add comment