crossword puzzle creation

75 views
Skip to first unread message

Brian Schott

unread,
Oct 31, 2025, 3:53:21 PMOct 31
to fo...@jsoftware.com
I have been attempting to do something like the suggested task at the following link to create a crossword puzzle .

https://rosettacode.org/wiki/Rosetta_Code:Village_Pump/Suggest_a_programming_task#Games

The steps below are suggestive of my approach and I would like ideas of how to complete part of the task.

   grid=: 0 : 0
......#......
.#.#.#.#.#.#.
.......#.....
.#.###.#.#.#.
.....#.......
##.#.#.#.###.
...#.....#...
.###.#.#.#.##
.......#.....
.#.#.#.###.#.
.....#.......
.#.#.#.#.#.#.
......#......
)
   $>LF cut grid
13 13
   data=:>LF cut grid
 

   [acrossStarts=:<@I. 3 '#..'&-:\"1 '#',.data

+---++---++---++------++---++---++---+

|0 7||0 8||0 6||0 4 10||0 8||0 6||0 7|

+---++---++---++------++---++---++---+

   [downStarts=:<@I. 3 '#..'&-:\"1 '#',.|:data

+---++---++---++-++----++---++---+

|0 6||0 8||0 4||1||0 10||0 6||0 8|

+---++---++---++-++----++---++---+




NB. downIns (see below) is a table of boxed pairs 

NB.   which gives index pairs of all the positions 

NB.   that require a puzzle index number for DOWN

NB.   clues and I want to use each pair to 

NB.   place a 1 (or some marker) in an 

NB.   initially empty 13 by 13 table of boxes


     emptyTable =: 13 13$a:


NB.   using the j conjunction "amend".

NB.   But I  am struggling with preparing the

NB.   input to the amend. That's where I need

NB.   help.

NB.  emptyTable does not have to be boxes at this

NB.    point, it could just be zeroes, if that is

NB.    easier. So a sparse array might be easier.

NB.    Later the results in emptyTable could 

NB.    produce the boxed array.

NB.  

NB. (startIns (not yet done) produces a similar

NB.   parallel problem.)

NB. 


NB. line wrap on next line

   [downIns=:,.&.>/"_1(({~(*@#&>)#i.@#),:~" 1 0([:<"0 (*@#&>)#i.@#)) downStarts

+----+----+----+----+-----+----+----+

|0 0 |0 0 |0 0 |0 1 |0  0 |0 0 |0 0 |

|0 6 |0 8 |0 4 |    |0 10 |0 6 |0 8 |

+----+----+----+----+-----+----+----+

|2 0 |2 0 |2 0 |2 1 |2  0 |2 0 |2 0 |

|2 6 |2 8 |2 4 |    |2 10 |2 6 |2 8 |

+----+----+----+----+-----+----+----+

|4 0 |4 0 |4 0 |4 1 |4  0 |4 0 |4 0 |

|4 6 |4 8 |4 4 |    |4 10 |4 6 |4 8 |

+----+----+----+----+-----+----+----+

|6 0 |6 0 |6 0 |6 1 |6  0 |6 0 |6 0 |

|6 6 |6 8 |6 4 |    |6 10 |6 6 |6 8 |

+----+----+----+----+-----+----+----+

|8 0 |8 0 |8 0 |8 1 |8  0 |8 0 |8 0 |

|8 6 |8 8 |8 4 |    |8 10 |8 6 |8 8 |

+----+----+----+----+-----+----+----+

|10 0|10 0|10 0|10 1|10  0|10 0|10 0|

|10 6|10 8|10 4|    |10 10|10 6|10 8|

+----+----+----+----+-----+----+----+

|12 0|12 0|12 0|12 1|12  0|12 0|12 0|

|12 6|12 8|12 4|    |12 10|12 6|12 8|

+----+----+----+----+-----+----+----+



NB. The example diagram supplied at rosettacode is flawed: 

NB. there is a missing third row and the clue indices

NB. 9 and 10 do not appear, as a result.


I'm sure my explanation here is lacking, but perhaps someone will understand my intent and can give pointers.

--

(B=)

Brian Schott

unread,
Oct 31, 2025, 11:04:18 PMOct 31
to fo...@jsoftware.com
Oops. I see now that my construction of the array downIns is wrong and I will work more on that.
There should be only 13 pairs of values in one row, not 7 rows with 13 pairs each. But I still don't know how to 
put the values in such a row into the amend.
--
(B=) <-----my sig
Brian Schott

Henry Rich

unread,
Nov 1, 2025, 3:54:56 AMNov 1
to forum
It might be easier for us to help if you can give an example of what you are trying to achieve with your amend. 

Henry Rich

To unsubscribe from this group and stop receiving emails from it, send an email to forum+un...@jsoftware.com.

trx2358...@yahoo.com

unread,
Nov 1, 2025, 4:09:45 AMNov 1
to Digest Recipients
The rosetta example looks buggy to me.  I got 3 down as being only length three from the initial diagram but the expanded one makes it look like it should be two.


Mike Day

unread,
Nov 1, 2025, 6:25:14 AMNov 1
to fo...@jsoftware.com
Agreed.  There are 13 rows in the initial unnumbered example,
but the expanded diagram with 2x2 cell interiors and "light" 
numbers has only 12 rows,  omitting expanded row 3 (origin 1 !) 
along with generated numbers 9 & 10.  It suggests the proposer 
drew/typed out the example manually.

I'm tempted to have a go,  but am currently stumped by the end-game 
In today's (London) Times Listener Crossword 4892.  Happy to 
send a copy of its pdf to interested parties,  but it's not a mathematical 
puzzle.

Mike

Sent from my iPad

On 1 Nov 2025, at 08:09, trx2358-discord via forum <fo...@jsoftware.com> wrote:

 The rosetta example looks buggy to me.  I got 3 down as being only length three from the initial diagram but the expanded one makes it look like it should be two.
To unsubscribe from this group and stop receiving emails from it, send an email to forum+un...@jsoftware.com.

Brian Schott

unread,
Nov 1, 2025, 9:42:21 AMNov 1
to fo...@jsoftware.com

Henry,

Thanks for the suggestion.

I'm trying to amend something like the following, but of course the boxes are of different shapes.
(and I have not yet fixed downIns, but I have a plan; I have appointments all day today, though. My planned change may produce the desired index pairs directly and I may not need to fix the "different shape" problem after all. Stay tuned.)


Below shows an example of what I would like. In the example I would like 13 empty cells to be replaced with <1 in any order of execution.  
(A simple example of what WORKS is as follows for 2 cells in a 3x7 empty array. But I cannot force my "different shape" argument into the desired format.)


( <1) ((1 1;2 2) }) ] 3 7$a:

   >6{ </. downIns
+---+---+----+---+---+----+----+
|0 0|2 0|4  0|6 1|8 0|10 0|12 0|
|0 8|2 6|4 10|   |8 4|10 8|12 6|
+---+---+----+---+---+----+----+
   $ each >6{ </. downIns
+---+---+---+---+---+---+---+
|2 2|2 2|2 2|1 2|2 2|2 2|2 2|
+---+---+---+---+---+---+---+

(<1) (>6{ </. downIns) } 13 13$a:

Henry Rich

unread,
Nov 1, 2025, 10:04:34 AMNov 1
to fo...@jsoftware.com
I don't see the example you are referring to.

Are you amending inside a boxed array?  If so, have you looked at https://code.jsoftware.com/wiki/Vocabulary/AmendingBoxedStructures ?

Can you please specify

* y before the amend
* x and m that you want to use for the amend
* result of the amend

Henry Rich

Brian Schott

unread,
Nov 1, 2025, 11:43:46 AMNov 1
to fo...@jsoftware.com

   I believe I have a solution for the amend problem. It is shown below. 



grid=: 0 : 0
......#......
.#.#.#.#.#.#.
.......#.....
.#.###.#.#.#.
.....#.......
##.#.#.#.###.
...#.....#...
.###.#.#.#.##
.......#.....
.#.#.#.###.#.
.....#.......
.#.#.#.#.#.#.
......#......
)
   $>LF cut grid

   data=:>LF cut grid

   [acrossStarts=:<@I. 3 '#..'&-:\"1 '#',.data

   [downStarts=:<@I. 3 '#..'&-:\"1 '#',.|:data

emptyTable =: 13 13$a:


  downIns=: ;/;(({~(*@#&>)#i.@#)(,.)each"0~" 1 ([:<"0 (*@#&>)#i.@#)) downStarts


   
   9!:7'+++++++++|-'

  
   (<1) downIns } emptyTable
+-+-+++-++-++-++-+++
|1| ||| ||1|| || |||
+-+-+++-++-++-++-+++
| | ||| || || || |||
+-+-+++-++-++-++-+++
|1| ||| || ||1|| |||
+-+-+++-++-++-++-+++
| | ||| || || || |||
+-+-+++-++-++-++-+++
|1| |||1|| || || |||
+-+-+++-++-++-++-+++
| | ||| || || || |||
+-+-+++-++-++-++-+++
| |1||| || || || |||
+-+-+++-++-++-++-+++
| | ||| || || || |||
+-+-+++-++-++-++-+++
|1| ||| || || ||1|||
+-+-+++-++-++-++-+++
| | ||| || || || |||
+-+-+++-++-++-++-+++
|1| ||| ||1|| || |||
+-+-+++-++-++-++-+++
| | ||| || || || |||
+-+-+++-++-++-++-+++
|1| ||| || ||1|| |||
+-+-+++-++-++-++-+++
   


(B=) 

Michael Day

unread,
Nov 2, 2025, 8:48:38 AMNov 2
to fo...@jsoftware.com

This doesn't attempt to answer Brian's questions,  as I'm not sure what they are.  

Instead,  it's my take on solving the proto-Rosetta problem.  

I find it easier to analyse ravels of the grid,  and its transpose.  For this to work nicely, 

it's best to border the grid with walls of blocked cells,  eg a mini-grid such as 

....

.#.#

....

.#.#


becomes 

######
#....#
#.#.##
#....#
#.#.##
######


whose across ravel is 

#######....##.#.###....##.#.########


Examine the ravels for lights with 2 or more cells by pattern matching against 

+----+-----+------+
|#..#|#...#|#....#|   .......... etc
+----+-----+------+


Place 1s in a numerical grid for all the across lights,  and do the same with all 

down lights,  identified by similar pattern matching on the ravelled transpose. 


Accumulate all light starting cells in the ravelled non-transposed grid.  The lights' 

lengths are easily found as they're the lengths of the matching patterns (less 2 for 

the bounding '#' ).


Here's the code:  (I THINK it's self-contained,  but I might have omitted something!)

The input is in the format of Brian's example.

    
construct =: {{
NB. border grid with block characters #
s     =. $ g =. h,. h, h,.~ y, h =. '#'
NB. create patterns for each possible light size > 1,  eg #...# for a light of 3 cells
NB.   szs is array of possible sizes 
pats  =. {{ '#' 0 _1 } '.'#~y+2}}  each szs =. }. >: i. >./ s
NB. Block for across lights 
NB. find indices of starts of across lights
apos  =. g&{{ x&{{  >: I.(,x) E.~ y}} each y }} pats
NB. save lengths of across lights by suitable expanding szs array
aszs  =. szs#~ #every apos
apos  =. ;apos
NB. set up a numeric grid with _1 for blocked cells,  and 1 for across start cells
new   =. s $ 1 apos } - , g = h
NB. Block for down lights - just by working on transpose of grid 
NB. find indices of starts of down lights
dpos  =. (|:g)&{{ x&{{ >: I.(,x) E.~ y}} each y }} pats
NB. save lengths of down lights by suitable expanding szs array
dszs  =. szs#~ #every dpos
dpos  =. ;dpos
NB. Amend with 1s for down start cells
new   =. |: (|.s) $ 1 dpos } ,|:new

NB. crosswords' "lights" are numbered from left to right and then down, 
NB. so accumulate the 1s for each start cell in the ravelled array and then reshape 
nums  =. s $ (* +/\ ) 0 >. , new
NB.    and recover the lists of across & down lights
anums =. apos { ,nums
dnums =. dpos { ,|: nums

NB. Assemble the expanded grid array applying cell verb to each cell
NB. nums + 0 <. new combines light start cell numbers with blocked cell indicators 
boxch =. 9!:6 ''     NB. Safer to use simple characters for bos bounds - saving session box chars 
9!:7 '+++++++++|-'
g     =. cell each }."1 }:"1 }.}: nums + 0 <. new

NB. Assemble the list of Across & Down lights and their lengths
clues =. (/:~) each (anums,.aszs);dnums,.dszs
clues =. ,/>('Across';'Down'),each {{ (":,.{."1 y) ,. ' ',.{{ '(',')',~":{:y }}"1 y}} each clues

NB. Output the whole 
o =. (": g) , clues
9!:7 boxch           NB. restore session box chars 
o
}}

NB. output a blank, blocked or numbered cell 
cell =: {{ 
NB. 2x4 internal shape seems to work quite nicely 
2 4 cell y
:
select. y
   case._1 do. 
      c =. x $'#'
   case. 0 do. 
      c =. x $' '
   case.   do. 
      c =. x{. ' ',:~ ":y
end.
NB.    '+||',. '---',  NB. if doing own boxing
   c
}}


And here's its output:  (looks ok in fixed width in this draft):


NB. doing Brian's example,  and couple of extreme cases 


   ,.construct each grid; (1 1 $ '.') ; 1 1 $'#'
+------------------------------------------------------------------+
|+----+----+----+----+----+----+----+----+----+----+----+----+----+|
||1   |    |2   |    |3   |    |####|4   |5   |    |6   |    |7   ||
||    |    |    |    |    |    |####|    |    |    |    |    |    ||
|+----+----+----+----+----+----+----+----+----+----+----+----+----+|
||    |####|    |####|    |####|8   |####|    |####|    |####|    ||
||    |####|    |####|    |####|    |####|    |####|    |####|    ||
|+----+----+----+----+----+----+----+----+----+----+----+----+----+|
||9   |    |    |    |    |    |    |####|10  |    |    |    |    ||
||    |    |    |    |    |    |    |####|    |    |    |    |    ||
|+----+----+----+----+----+----+----+----+----+----+----+----+----+|
||    |####|    |####|####|####|    |####|    |####|    |####|    ||
||    |####|    |####|####|####|    |####|    |####|    |####|    ||
|+----+----+----+----+----+----+----+----+----+----+----+----+----+|
||11  |    |    |    |12  |####|13  |    |    |    |    |    |    ||
||    |    |    |    |    |####|    |    |    |    |    |    |    ||
|+----+----+----+----+----+----+----+----+----+----+----+----+----+|
||####|####|    |####|    |####|    |####|    |####|####|####|    ||
||####|####|    |####|    |####|    |####|    |####|####|####|    ||
|+----+----+----+----+----+----+----+----+----+----+----+----+----+|
||14  |    |    |####|15  |    |    |    |    |####|16  |    |    ||
||    |    |    |####|    |    |    |    |    |####|    |    |    ||
|+----+----+----+----+----+----+----+----+----+----+----+----+----+|
||    |####|####|####|    |####|    |####|    |####|    |####|####||
||    |####|####|####|    |####|    |####|    |####|    |####|####||
|+----+----+----+----+----+----+----+----+----+----+----+----+----+|
||17  |    |18  |    |    |    |    |####|19  |    |    |    |20  ||
||    |    |    |    |    |    |    |####|    |    |    |    |    ||
|+----+----+----+----+----+----+----+----+----+----+----+----+----+|
||    |####|    |####|    |####|    |####|####|####|    |####|    ||
||    |####|    |####|    |####|    |####|####|####|    |####|    ||
|+----+----+----+----+----+----+----+----+----+----+----+----+----+|
||21  |    |    |    |    |####|22  |    |23  |    |    |    |    ||
||    |    |    |    |    |####|    |    |    |    |    |    |    ||
|+----+----+----+----+----+----+----+----+----+----+----+----+----+|
||    |####|    |####|    |####|    |####|    |####|    |####|    ||
||    |####|    |####|    |####|    |####|    |####|    |####|    ||
|+----+----+----+----+----+----+----+----+----+----+----+----+----+|
||24  |    |    |    |    |    |####|25  |    |    |    |    |    ||
||    |    |    |    |    |    |####|    |    |    |    |    |    ||
|+----+----+----+----+----+----+----+----+----+----+----+----+----+|
|Across                                                            |
| 1 (6)                                                            |
| 4 (6)                                                            |
| 9 (7)                                                            |
|10 (5)                                                            |
|11 (5)                                                            |
|13 (7)                                                            |
|14 (3)                                                            |
|15 (5)                                                            |
|16 (3)                                                            |
|17 (7)                                                            |
|19 (5)                                                            |
|21 (5)                                                            |
|22 (7)                                                            |
|24 (6)                                                            |
|25 (6)                                                            |
|Down                                                              |
| 1 (5)                                                            |
| 2 (7)                                                            |
| 3 (3)                                                            |
| 5 (9)                                                            |
| 6 (5)                                                            |
| 7 (7)                                                            |
| 8 (11)                                                           |
|12 (9)                                                            |
|14 (7)                                                            |
|16 (7)                                                            |
|18 (5)                                                            |
|20 (5)                                                            |
|23 (3)                                                            |
|                                                                  |
|                                                                  |
+------------------------------------------------------------------+
|+----+                                                            |
||    |                                                            |
||    |                                                            |
|+----+                                                            |
|Across                                                            |
|Down                                                              |
+------------------------------------------------------------------+
|+----+                                                            |
||####|                                                            |
||####|                                                            |
|+----+                                                            |
|Across                                                            |
|Down                                                              |
+------------------------------------------------------------------+


There are probably some cases which lead to failure;  1x1 grids with a single  dot or hash 

seem to produce acceptable output.    


It's a bit more prolix than I'd hoped.  Any use? 


Mike


Virus-free.www.avast.com

Brian Schott

unread,
Nov 2, 2025, 10:53:39 AMNov 2
to fo...@jsoftware.com
Michael,

Your script looks great but I am getting a huge readout upon execution and wonder if you can tell me the problem.
Your solution to the "proto" task is much more than I asked for; I have been touching up my own needs and working on the part of your "cell" code, in effect. My approach is much less elegant and as yet unfinished. Also my code does not ravel the grid, but that is attractive, too.
Thank you for sharing this terrific code. Also I learned the word prolix as I searched for its meaning. I thought you were unnecessarily self-deprecating by suggesting it.

From my command below you can see that the output was shaped 553 6 in the first box.

   $each construct each grid; (1 1 $ '.') ; 1 1 $'#'

┌─────┬───┬───┐

│553 6│6 6│6 6│

└─────┴───┴───┘



The only thing I did was to load your (saved) script and added the definition of grid:


      grid=: 0 : 0

......#......

.#.#.#.#.#.#.

.......#.....

.#.###.#.#.#.

.....#.......

##.#.#.#.###.

...#.....#...

.###.#.#.#.##

.......#.....

.#.#.#.###.#.

.....#.......

.#.#.#.#.#.#.

......#......

)

      JVERSION

Engine: j9.5.2/j64arm/darwin

Build: commercial/2024-02-02T18:38:04/clang-14-0-0/SLEEF=1

Library: 9.5.5

Platform: Darwin 64

Installer: j9.5 install

InstallPath: /users/brian/j9.5

Contact: www.jsoftware.com



Brian Schott

unread,
Nov 2, 2025, 11:02:38 AMNov 2
to fo...@jsoftware.com

I have attached the script with this email. Name is misspelled, though.

crosswordMichaielDay.ijs

Michael Day

unread,
Nov 2, 2025, 5:34:12 PMNov 2
to fo...@jsoftware.com

Sorry - I should have included my definition of "grid" - my script expects 

it to be a simple character array,  whereas you've defined a character string 

delimited by LF.  So my code is handling what I think you regard as" > data " 

So,  after loading your copy of my script,  I get: 

   $construct grid                  NB. ugh!
553 6
   $construct > LF cut grid   NB. what you need
72 66

APologies for blowing up your terminal screen!

Mike 

To unsubscribe from this group and stop receiving emails from it, send an email to forum+un...@jsoftware.com.

Virus-free.www.avast.com

Joshua Y

unread,
Nov 3, 2025, 7:24:00 AMNov 3
to forum
I had fun with this one, and figured it might be interesting seeing the solution from another mind.

I'm just going to share a playground link rather than dump my code here.

I'm cheating a little bit here; not all squares are 2x4 char matrices, but it's a minor thing and pretty easy to fix.

Mike Day

unread,
Nov 3, 2025, 10:29:14 AMNov 3
to fo...@jsoftware.com
Very nice,  and far from prolix!... viz Brian's comment on my self-criticism.

I'd started working with the character array,  but do usually resort to a 
Boolean or small integer representation for this sort of thing,  as you do 
from the outset.   I also considered doing the downs using the under 
construct.   I don't see how you're "cheating"...  the aspect ratio of the 
cells is surely just a matter of taste,  and,  perhaps,  of the vagaries of 
one's device.

Mike

Sent from my iPad

On 3 Nov 2025, at 13:36, Joshua Y <josh...@gmail.com> wrote:



Brian Schott

unread,
Nov 3, 2025, 11:52:55 AMNov 3
to fo...@jsoftware.com
Joshua, 
I agree with Mike and also think your solution is SLICK and efficient.
The playground is a perfect delivery venue.
Thanks, much,


Joshua Y

unread,
Nov 3, 2025, 5:56:08 PMNov 3
to forum
  > I don't see how you're "cheating"

I only meant in terms of the formatting of the crossword.
If you create a crossword which has full column length words (no black squares in a column), that column will be drawn only 1 or 2 chars wide.

Mike Day

unread,
Nov 3, 2025, 7:02:57 PMNov 3
to fo...@jsoftware.com, forum
OK....  I changed the # to a dot in the last column,  
which was then rendered with a width of 1 char, 
so see the minor problem.

BUT,  you can avoid this feature by appending a row 
of all # to the input grid and then removing the last 
3 rows of the rendered grid,  with minimal extra code. 

Cheers,

Mike

Sent from my iPad

On 3 Nov 2025, at 22:56, Joshua Y <josh...@gmail.com> wrote:



Joshua Y

unread,
Nov 3, 2025, 7:58:00 PMNov 3
to forum, forum
My quick-fix would be something like this 

cw =. (* ,:@":@{. ])&.> n =. (>: i. +/ , sp) si} sp
cw =. 2 4 {.L:0 (<2 4 $ '#') (($ #: I.@,) grid)} cw

I don't like the repeating of `2 4`, but it's not worth getting too worked up over.

Also, it occurs to me that `Fmt` could be done with sprintf

load 'format/printf'
Fmt =: '%d (%d)' sprintf ]

But there's a charm to solving everything with the primitives.
Reply all
Reply to author
Forward
0 new messages