Manipulating the 81 digit puzzle string with unix commands

Programs which generate, solve, and analyze Sudoku puzzles

Manipulating the 81 digit puzzle string with unix commands

Postby coloin » Sat May 07, 2022 12:10 am

I have had a brief look at the old "programmers forum" and didnt find any thing

I am lucky enough and thankful to benefit from the expertise of various programmers over the years

With the use of generally available unix software I am able to process files including automated batch files to generate puzzles.

Essentially I am manipulating the 81 digit puzzle string in a .txt file.

However there are not any unix commands posted that I can find apart from brief reference here

These are some I have successfully used and I plan to document them in the next post for reference.

Undoubtably there are other known commands which are above my level of expertise to compile and I am grateful for any contribution !
coloin
 
Posts: 2381
Joined: 05 May 2005
Location: Devon

Manipulating the 81 digit puzzle string with unix commands

Postby coloin » Sat May 07, 2022 12:14 am

Here are a few command lines and will update a few more
Code: Select all
grep                                                                 
delete lines with #                                               
grep32 -v # test.txt > testsol.txt                           
                                                                     
print lines with  #                                               
grep32  '#'                                 
                                                                     
print lines ending in #                                           
grep32  '#$'                                   
                                                                     
print lines starting with #                                       
grep32  '^#

Code: Select all
sed                                                                 
change 0 to .                                                       
sed s/0/./g                                                         
                                                                     
remove first 10 lines                                               
sed -r s/.{10}//                                                     
                                                                     
remove last 81 lines                                                 
sed -r s/.{81}$//                                                   
                                                                     
change the 13th character to a 2      [ 0 to 80 in this instance]   
sed s/\(.\{12\}\).\{1\}/\12/
                          ^
                          |
coloin
 
Posts: 2381
Joined: 05 May 2005
Location: Devon

Re: Manipulating the 81 digit puzzle string with unix comman

Postby coloin » Sat May 07, 2022 12:24 am

In particular , despite searching unix Q&A threads I am unble to generate a command which flips the puzzle over the diagonal ....
Code: Select all
+---+---+---+
|\..|...|...|
|.\.|...|...|
|..\|...|...|
+---+---+---+
|...|\..|...|
|...|.\.|...|
|...|..\|...|
+---+---+---+
|...|...|\..|
|...|...|.\.|
|...|...|..\|
+---+---+---+

Code: Select all
 1 2 3 4 5 6 7 8 9                                                                   
101112131415161718                                                                 
192021222324252627                                                                 
282930313233343536                                                                 
373839404142434445                                                                 
464748495051525354                                                                 
555657585960616263                                                                 
646566676869707172                                                                 
737475767778798081


1,11,21 .....etc stay the same
2 goes to 10 10 goes to 2 ....etc

If this isnt too cumbersome, then some of the other morphing transformations could be done ...
coloin
 
Posts: 2381
Joined: 05 May 2005
Location: Devon

Postby 1to9only » Sat May 07, 2022 9:23 am

coloin wrote:In particular , despite searching unix Q&A threads I am unble to generate a command which flips the puzzle over the diagonal ....

I dont think any unix command(s) will do this in an easy manner! Bash with awk might be able to do it!!

On Windows, my solution is to write such small utility programs in python. If I use it often enough, it gets converted to C and compiled to .exe.

python code:
flip.py: Show
Code: Select all
#! /usr/bin/python
this_program = "flip.py"
this_version = "1.00"
import os, sys, optparse

# usage:
# flip.py            <- input: puzzles.txt output: puzzlesout.txt
# flip.py test.txt   <- input: test.txt    output: testout.txt

def main():
   parser = optparse.OptionParser()
   argc, argv = parser.parse_args()

   fn = 'puzzles.txt'
   fo = 'puzzlesout.txt'

   if len( argv) == 1:
      fn = argv[ 0]
      fo = fn.replace( '.txt', 'out.txt')

   isfile = os.path.isfile( fn)
   if not isfile:
      print( fn + ' not found')
      exit( 0)

   pl = 0
   f = open( fn, 'r')
   g = open( fo, 'w')
   for line in f:
      output = line

      # flip along diagonal (\)
      # cell[ row][ col] = cell[ col][ row]

      if len( line) >= 81:
         for row in range( 9):
            for col in range( 9):
               tgt = row*9 + col
               src = col*9 + row

               # this replaces one character at a time, it is slow!

               output = output[ :tgt] + line[ src:src+1] + output[ tgt+1:]

      g.write( output)
      pl += 1

   g.close()
   f.close()

   print( str( pl) + ' line(s) processed.')

   return 0;

if __name__ == "__main__":
   sys.exit( main())


usage:
Code: Select all
flip.py            <- input: puzzles.txt output: puzzlesout.txt
flip.py test.txt   <- input: test.txt    output: testout.txt

test.txt:
Code: Select all
...8..2...9..4...7.....1.8.1..3.5....7..2......56.8...8.....3....6....18.2.....5. ED=1.5/1.2/1.2

Code: Select all
...8..2..
.9..4...7
.....1.8.
1..3.5...
.7..2....
..56.8...
8.....3..
..6....18
.2.....5. ED=1.5/1.2/1.2

testout.txt:
Code: Select all
...1..8...9..7...2.....5.6.8..3.6....4..2......15.8...2.....3....8....15.7.....8. ED=1.5/1.2/1.2

Code: Select all
...1..8..
.9..7...2
.....5.6.
8..3.6...
.4..2....
..15.8...
2.....3..
..8....15
.7.....8. ED=1.5/1.2/1.2

The python script can be used as template, modified for other manipulations, e.g. to flip along other diagonal:
Code: Select all
tgt = (8-row)*9 + (8-col)
User avatar
1to9only
 
Posts: 4175
Joined: 04 April 2018

Re: Manipulating the 81 digit puzzle string with unix comman

Postby dobrichev » Sat May 07, 2022 10:33 am

coloin wrote:However there are not any unix commands posted that I can find apart from brief reference here
These are some I have successfully used and I plan to document them in the next post for reference.
Undoubtably there are other known commands which are above my level of expertise to compile and I am grateful for any contribution !

Take a look here for few more examples.

Transposing is too specific to be resolved by builtin linux commands. Use several lines of code in some programming language instead.
dobrichev
2016 Supporter
 
Posts: 1850
Joined: 24 May 2010

Re: Manipulating the 81 digit puzzle string with unix comman

Postby StrmCkr » Sun May 15, 2022 9:39 am

the code below is how i do any of the isomorphic changes in my solver:
{in Free pascal} Im sure there is better methods but i know these work.

mine manipulates the grid string then refreshes the Rn,Cn,Bn spaces that the changes effected.
{sucks as it currently resets pm states for my solver}

Code: Select all
procedure issomorph( K2,B2,F2:Char);
var
K,B,F:char;
xn,xl,n:integer;
S2:  array [cell] of nums;  {solved grid copy}

begin

for xn:= 0 to 80 do
 begin
 s2[xn]:=S[xn];

 end;

initiate;

for xn:= 0 to 80 do
 s[xn]:=s2[xn];

k:=k2;
b:=b2;
f:=f2;

if not (K in ['d','t','s','b','c','r','m','p'])
 then
   begin
writexy(2,28,' Which area to move?');
writexy(2,29,' D{igit},R{ow},C{ol},S{tack},B{and},T{ranspose},M{irror},P{ivot}');
K:=readkey;
gotoxy(23,28); write(': ',K);
   end;

 case K of

{R} #114:
 begin

   if not (B in ['1'..'9'])
    then
     begin
   writexy(2,30,' Which Row to move? {1..9}');
   B:=readkey;  write(': ',B);
     end;

   if not (F in ['1'..'9'])
    then
     begin
   writexy(2,31,' Swaping with Row?');

   case B of
    #49,#50,#51 : write(' 1,2,3');
    #52,#54,#55 : write(' 4,5,6');
    #56,#57,#58 : write(' 7,8,9');

   end;

   F:=readkey; write(': ',F);
    end;

   for xn:=0 to 8 do
    begin

    s[Rset[(ord(b)-48)-1,xn]]:= S2[Rset[(ord(f)-48)-1,xn]];
    s[Rset[(ord(f)-48)-1,xn]]:= S2[Rset[(ord(b)-48)-1,xn]];   

    end;

  end;  {row}

{C} #99:
 begin

  if not (B in ['1'..'9'])
    then
     begin
   writexy(2,30,' Which Col to move? {1..9}');
   B:=readkey;  write(': ',B);
     end;

   if not (F in ['1'..'9'])
    then
     begin
   writexy(2,31,' Swaping with Col?');

   case B of
    #49,#50,#51 : write(' 1,2,3');
    #52,#54,#55 : write(' 4,5,6');
    #56,#57,#58 : write(' 7,8,9');

   end;

   F:=(readkey); write(': ',F);
    end;
   
   for xn:=0 to 8 do
    begin

    s[Cset[(ord(b)-48)-1,xn]]:= S2[Cset[(ord(f)-48)-1,xn]];
    s[Cset[(ord(f)-48)-1,xn]]:= S2[Cset[(ord(b)-48)-1,xn]];

    end;

 end; {col}

{Band} #98:
 begin

    if not (B in ['1'..'3'])
    then
     begin
   writexy(2,30,' Which Band to Swap? {1..3}');
   B:=readkey;  write(': ',B);
     end;

    if not (F in ['1'..'3'])
    then
     begin
   writexy(2,31,' Swaping with Band? {1..3}');
   F:=readkey;  write(': ',F);
      end;

   For xn:= 0 to 8 do
    for n:= 0 to 2 do
      begin
        s[Rset[(((ord(b)-48)-1)*3+n),xn]]:=s2[Rset[(((ord(f)-48)-1)*3+n),xn]];
        s[Rset[(((ord(f)-48)-1)*3+n),xn]]:=s2[Rset[(((ord(b)-48)-1)*3+n),xn]];   
      
      
      end;

 end;  {Band}

{stack} #115:
 begin

     if not (B in ['1'..'3'])
    then
     begin
   writexy(2,30,' Which Stack to Swap? {1..3}');
   B:=readkey;  write(': ',B);
     end;

    if not (F in ['1'..'3'])
    then
     begin
   writexy(2,31,' Swaping with Stack? {1..3}');
   F:=readkey;  write(': ',F);
      end;

   For xn:= 0 to 8 do
    for n:= 0 to 2 do
      begin
        s[Cset[(((ord(b)-48)-1)*3+n),xn]]:=s2[Cset[(((ord(f)-48)-1)*3+n),xn]];
        s[Cset[(((ord(f)-48)-1)*3+n),xn]]:=s2[Cset[(((ord(b)-48)-1)*3+n),xn]];
      
      
      end;

 end; {stack}

{Transpose} #116:
 begin

 if not(k2 in['t'])
 then
 writexy(2,30,' Transposing Grid (Diagonal reflection & Anti Diagonal Reflection)');
 if not (b in ['1'..'2'] )
  then begin
 writexy(2,31,' Diagonal / Anti Diagonal ? {1,2} ');
   B:=readkey;  write(': ',B);
   end;

  if b = '1' then begin
 for xn:= 0 to 8 do
  for n:= 0 to 8 do
   begin

     S[Rset[xn,n]]:=s2[Cset[xn,n]];

    end;
 end;

  if b = '2' then begin
  for xn:= 8 downto 0 do
   for n:= 8 downto 0 do
   begin

   S[Rset[n,xn]]:=s2[Cset[8-n,8-xn]];
      
   end;
   end;

 end; {Transpose}

{D} #100:
 begin

  if not (b in ['1'..'9'] )
   then
   begin
  writexy(2,30,' Which Digit to Swap? {1..9}');
   B:=readkey;  write(': ',B);
   end;

  if not (f in ['1'..'9'] )
   then
   begin
   writexy(2,31,' Swaping with Digit {1..9}');
   F:=readkey;  write(': ',F);
    end;

   For xn:= 0 to 80 do
   begin

    if S2[xn]= [ord(b)-48 ]
      then
      begin
        s[xn]:=[ord(F)-48];
      
      end;

    if S2[xn]= [ord(F)-48 ]
      then
      s[xn]:=[ord(B)-48];
    end;

 end;

 {Mirror} #109: begin
 if not(k2 in['m'])
 then
 writexy(2,30,' Mirror Grid (Reflection)');
 if not (b in ['1'..'2'] )
  then begin
 writexy(2,31,' Horizontal / Vertical ? {1,2}');
   B:=readkey;  write(': ',B);
   end;

   if B ='1'
     then
     begin
      for n:= 0 to 8 do
      for xn:= 0 to 8 do
      S[rset[xn,n]]:=S2[Rset[(8-xn),n]];
     end;

   if B ='2'
     then
     begin
      for n:= 0 to 8 do
      for xn:= 0 to 8 do
      S[Cset[xn,n]]:=S2[Cset[(8-xn),n]];
     end;

 end;

 {Pivot/quater turn} #112:
 begin

 if not(k2 in['p'])
 then
 writexy(2,30,' Pivot Grid ( 1/4 turn)');
 if not (b in ['1'..'2'] )
  then begin
 writexy(2,31,' Left / Right ? {1,2}');
   B:=readkey;  write(': ',B);
   end;

  if b = '1' then begin
 for xn:= 0 to 8 do
  for n:= 8 downto 0 do
   begin

     S[Cset[xn,(8-n)]]:=s2[Rset[xn,n]];

    end;
 end;

  if b = '2' then begin
  for xn:= 8 downto 0 do
   for n:= 0 to 8 do
   begin

   S[Cset[xn,n]]:=s2[Rset[(8-xn),n]];

   end;
   end;

 end; {pivit}
   end;

if not (K2 in ['d','t','s','b','c','r','m','p'])
 then
   begin
writexy(2,28,'                                                ');
writexy(2,29,'                                                                  ');
writexy(2,30,'                                                                  ');
writexy(2,31,'                                      ');
end;

for xL:=0 to 80 do
 if s[xl] <> [] then
    begin
      nsector[Rx[xl]]:=nsector[rx[xl]] + s[xl];
      nsector[Cy[xl]+9]:=nsector[cy[xl]+9] + s[xl];
      nsector[bxy[xl]+18]:=nsector[Bxy[xl]+18] + s[xl];
    
        exclude(ocell,xl);
      include(Acell,xl);      
     end;

 Sbrc;
 errorcheck;
 wpm(1,0,0);

end;  {isomorphic transformation}
Last edited by StrmCkr on Sun May 15, 2022 10:14 am, edited 1 time in total.
Some do, some teach, the rest look it up.
stormdoku
User avatar
StrmCkr
 
Posts: 1425
Joined: 05 September 2006

Re: Manipulating the 81 digit puzzle string with unix comman

Postby StrmCkr » Sun May 15, 2022 10:05 am

Some do, some teach, the rest look it up.
stormdoku
User avatar
StrmCkr
 
Posts: 1425
Joined: 05 September 2006

Re: Manipulating the 81 digit puzzle string with unix comman

Postby coloin » Mon May 16, 2022 9:41 am

Thanks for your replies ... I'm reassured that it wasn't an easy task with a simple solution ...
A small utility program might be the way,
coloin
 
Posts: 2381
Joined: 05 May 2005
Location: Devon

Re: Manipulating the 81 digit puzzle string with unix comman

Postby StrmCkr » Mon May 16, 2022 8:51 pm

yeah its not
for the 80 character string your replacing
0 no change
1st with the 9th
2nd with the 18th
10th no change
19th with the 11th
20th no change

etc
basically you'd need to a math function to convert position for its choice of swap

me i found its easier to cheat with a loop of
for xa:=0 to 2 do
for ya:=0 to 2 do
where
xa controls the row
and ya controls the col
{xa*3} + {ya*3) = [xa,ya] cell location reference chart look up
or
that (xa * 9 ) + ya = string position

still a 1:1 swap on the diagonal should be 36 swaps max.
(81-9 )/ 2
Some do, some teach, the rest look it up.
stormdoku
User avatar
StrmCkr
 
Posts: 1425
Joined: 05 September 2006

Re: Manipulating the 81 digit puzzle string with unix comman

Postby tdillon » Tue May 17, 2022 3:48 am

How's this for awk-free bash golf ...
Code: Select all
p="96.7..1.8..365.....4..3.52......4...8.7...24.45.1.96.3.2.5.6..76.8...9.1.7..13..."
seq 9|xargs -Ix bash -c "echo $p|egrep -o .{9}|cut -bx"|tr -d '\n';echo

Or for input file "in":
Code: Select all
while read -r p;do seq 9|xargs -Ix bash -c "echo $p|egrep -o .{9}|cut -bx"|tr -d '\n';echo;done <in

Or, longer, but if your tastes really call for processing each column in parallel:
Code: Select all
echo $p | egrep -o .{9} | bash -c "tee $(seq 9 | sed 's/./>(cut -b&>&)/' |xargs) >/dev/null" ; bash -c "cat $(seq 9 | sed 's/./<(tail -f &|head -n9)/' |xargs)" | tr -d '\n' ; echo
tdillon
 
Posts: 66
Joined: 14 June 2019

Re: Manipulating the 81 digit puzzle string with unix comman

Postby coloin » Tue May 17, 2022 8:51 pm

excellent .. if it works ... to the novice ...understanding what is happening is key
i need ...bash .... egrep = ? grep32 and others unix programs ?

swapping the bands [eg 1-2,][1-3[2-3] would also be a good one ... and I will try sed and merge for this...
coloin
 
Posts: 2381
Joined: 05 May 2005
Location: Devon

Re: Manipulating the 81 digit puzzle string with unix comman

Postby StrmCkr » Wed May 18, 2022 1:47 am

Bash is an add on script
if I'm reading it correct its not changing the string in any shape
Instead it's printing to screen the translation cell. Cycle to a but show b at x instead.
Some do, some teach, the rest look it up.
stormdoku
User avatar
StrmCkr
 
Posts: 1425
Joined: 05 September 2006

Re: Manipulating the 81 digit puzzle string with unix comman

Postby tdillon » Wed May 18, 2022 6:33 am

coloin wrote:understanding what is happening is key

Starting from the inside, egrep is an alias for "grep -E" (needed to use extended regexps), and -o tells it to just consume matching input leaving the rest for the next line. The regexp ".{9}" matches any 9 characters, so this splits the 81 character string into 9 lines. I realize now that this part can also be written more compactly and obscurely using a "here string" to provide egrep's input like so:

Code: Select all
$ egrep -o .{9}<<<$p
96.7..1.8
..365....
.4..3.52.
.....4...
8.7...24.
45.1.96.3
.2.5.6..7
6.8...9.1
.7..13...

"cut -bN" will read stdin and print the Nth character from each line, so to get the first column we have:

Code: Select all
$ egrep -o .{9}<<<$p|cut -b1
9
.
.
.
8
4
.
6
.

So we just want to do that for each of the 9 columns and then delete all the newlines (tr -d '\n').

For this I'm using "seq 9" to produce the digits 1..9 and then piping them to xargs, which, when given the argument -Ix executes the command to its right once for each input read from stdin while substituting that value for each occurrence of 'x' in the command. For example:

Code: Select all
$ seq 9 | xargs -Ix echo xzx
1z1
2z2
3z3
4z4
5z5
6z6
7z7
8z8
9z9

So xargs is placing each digit into cut's 'b' argument in the command "bash -c "egrep -o .{9}<<<$p|cut -bx"", where we have to execute each time in a subshell since without it the xargs command will end at the pipe.

Honesty it would be clearer and a little shorter to use a bash for loop, but less in the spirit of piping together a bunch of commands.
tdillon
 
Posts: 66
Joined: 14 June 2019

Re: Manipulating the 81 digit puzzle string with Python

Postby coloin » Sat Aug 06, 2022 3:36 pm

Thanks for your comments and advice .....

luckily i showed it to my son edmoind who knocked up a script in python to morph the puzzles as needed !!!!

requirements
python
python's numpy library

Program and a readme file Morpho

It can morph the bands [and rows if needed] and also do the reflection
I have included a batch file which provides versions of the 5 other morphed bands from one puzzle ... and combines using cat
coloin
 
Posts: 2381
Joined: 05 May 2005
Location: Devon

Re: Manipulating the 81 digit puzzle string with unix comman

Postby P.O. » Sat Aug 06, 2022 6:09 pm

hi coloin, maybe of some interest; i do the morphing by playing with these groups of permutations:
http://www.afjarvis.staff.shef.ac.uk/sudoku/sudgroup.html
for example Puzzle 46 is a morph of this one ...........1.2.3...5.6.1.9...35..2...6...4.7...8.1.4...2.9.7.1...4.8.5........... from PG336 + some relabelling.
Code: Select all
                from this pattern        to this pattern
               
               . . . . . . . . .         . X . X . . X X .
               . . X . X . X . .         X . . . X . . . X
               . X . X . X . X .         . . . . . . . . .
               . . X X . . X . .         X . . . X . . . X
               . X . . . X . X .         . X . X . . X X .
               . . X . X . X . .         . . . . . . . . .
               . X . X . X . X .         X . . . X . . . X
               . . X . X . X . .         X . . . X . . X .
               . . . . . . . . .         . X . X . . X . .
               
by applying in succession (22 23 2 22 23)
               
22
((1 31 61) (2 32 62) (3 33 63) (4 34 55) (5 35 56) (6 36 57) (7 28 58)
 (8 29 59) (9 30 60) (10 40 70) (11 41 71) (12 42 72) (13 43 64) (14 44 65)
 (15 45 66) (16 37 67) (17 38 68) (18 39 69) (19 49 79) (20 50 80) (21 51 81)
 (22 52 73) (23 53 74) (24 54 75) (25 46 76) (26 47 77) (27 48 78))

23
((1 31 71 11 41 81 21 51 61) (2 32 72 12 42 79 19 49 62)
 (3 33 70 10 40 80 20 50 63) (4 35 65 14 45 75 24 52 55)
 (5 36 66 15 43 73 22 53 56) (6 34 64 13 44 74 23 54 57)
 (7 28 67 17 38 77 27 48 60) (8 29 68 18 39 78 25 46 58)
 (9 30 69 16 37 76 26 47 59))

2
((7 8 9) (16 17 18) (25 26 27) (34 35 36) (43 44 45) (52 53 54) (55 64 73)
 (56 65 74) (57 66 75) (58 67 76) (59 68 77) (60 69 78) (61 71 81) (62 72 79)
 (63 70 80))

without relabelling:
Code: Select all
 ...........1.2.3...5.6.1.9...35..2...6...4.7...8.1.4...2.9.7.1...4.8.5...........
 .1.2..79.5...4...8.........3...1...2.9.5..16..........4...8...12...3..5..7.6..4..
 
          . . .   . . .   . . .       . 1 .   2 . .   7 9 .
          . . 1   . 2 .   3 . .       5 . .   . 4 .   . . 8
          . 5 .   6 . 1   . 9 .       . . .   . . .   . . .
          . . 3   5 . .   2 . .       3 . .   . 1 .   . . 2
          . 6 .   . . 4   . 7 .       . 9 .   5 . .   1 6 .
          . . 8   . 1 .   4 . .       . . .   . . .   . . .
          . 2 .   9 . 7   . 1 .       4 . .   . 8 .   . . 1
          . . 4   . 8 .   5 . .       2 . .   . 3 .   . 5 .
          . . .   . . .   . . .       . 7 .   6 . .   4 . .

P.O.
 
Posts: 1376
Joined: 07 June 2021


Return to Software