#!/usr/local/bin/perl # # Fri Sep 23 06:56:31 2011/hakank@bonetmail.com# # # Reads a crossword problem (grid) from a text file. # $|=1; use strict; use warnings; # use diagnostics; my $file = $ARGV[0] || die "Syntax: make_crossword3.pl gridfile\n"; open my $fh, "<", $file or die "Cannot open $file: $!"; my $grid = ""; while (<$fh>) { chomp; next if /^\s*[#%]/; $grid .= "$_\n"; } warn "GRID:\n$grid\n"; print crossword2($grid); # # Main routines # sub crossword2 { my ($grid) = @_; my ($problem, $max_letters) = make_problem($grid); my %crossword = (); my %crossword_transposed = (); my $r = 0; my $c = 0; for (split /\n/, $problem) { s/(?:^\s+|\s+$)//g; my @line = split /[^\d]+/; $c = 0; for (@line) { $crossword{$r}{$c} = $_; $crossword_transposed{$c}{$r} = $_; $c++; } $r++; } my $rows = $r; my $cols = $c; my @segments = (); get_segments(\%crossword, $rows, $cols, \@segments); get_segments(\%crossword_transposed, $cols, $rows, \@segments); my @tables = (); my $segments_str = ""; for (@segments) { my @segment = @{$_}; my $len = scalar @segment; my $s = join ", ", map {"L[$_]" } @segment; push @tables, "table([$s], words$len)"; $segments_str .= join ",", @segment; $segments_str .= join "", ",0" x ($cols - scalar @segment); $segments_str .= ",\n"; } my $num_segments = scalar @segments; my $table_str = join " \n/\\ ", @tables; my $date = scalar localtime; my $grid_presentation = join "\n", map {"% $_"} split /\n/, $grid; # # The MiniZinc model # return < 1 # that has number > 0. # sub get_segments { my ($h, $rows, $cols, $segments, $mode) = @_; my $c = 0; for my $row (0..$rows-1) { my @this_segment = (); for my $col (0..$cols-1) { my $v = $h->{$row}{$col} || 0; if ($v == 0) { if (@this_segment > 0 and $c > 0) { push @{$segments}, [@this_segment]; } @this_segment = (); } else { push @this_segment, $v; } $c++; } if (@this_segment > 0 and $c > 0) { push @{$segments}, [@this_segment]; } } } # # Make the word definitions # sub make_words { my ($words) = @_; my %words = (); for (@$words) { my @w = split //; my $len = scalar @w; push @{$words{$len}}, [@w]; } my $all_words_str = ""; for (sort {$a <=> $b} keys %words) { my @these_words = @{$words{$_}}; my $len = $_; my $w_str = ""; for (@these_words) { $w_str .= join ",", @$_; $w_str .= ",\n"; } my $num = scalar @these_words; $all_words_str .= <