#!/usr/bin/perl

#!C:\perl\bin\perl.exe

print "Content-type: text/html\n\n";  $ascii=0;
#print "Content-type: text/plain\n\n";  $ascii=1;

use Sys::Hostname;

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$isdist) = localtime time;
$sec="0".$sec if $sec<=9;
$min="0".$min if $min<=9;
$hour="0".$hour if $hour<=9;
$mday="0".$mday if $mday<=9;
$mon++; $mon="0".$mon if $mon<=9; 
$unique='-'.$sec.$min.$hour.$mday.$mon.$year;

$FORM{'level'}='logic';
for ($i=1;$i<=81;$i++) {
  @puzzle[$i] = "";
  $FORM{'p'.$i}="";
}
$rawData=$ENV{'QUERY_STRING'};
$length = length($rawData);
if ($length==0) {
  $length = $ENV{'CONTENT_LENGTH'};
  read (STDIN, $rawData, $length); 
}
print "length=$length\n" if $ascii==1;

if ($length!=0) {
  $rawData =~ tr/+/ /;
  $convData = $rawData;
  $convData =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C",hex($1))/eg;
  @args=split(/&/,$convData);
  foreach $pair (@args) {
    ($name, $value) = split(/=/, $pair);
    $i=index($name,'-');
    $name=substr($name,0,$i) if $i>0;
    $FORM{$name}=$value;
    print "$name=$value\n" if $ascii==1;
  }
  $offen=0;
  for ($i=1;$i<=81;$i++) {
    @puzzle[$i]=$FORM{'p'.$i};
    @hinter[$i]="ffffff";
    $offen++ if $FORM{'p'.$i} eq "";
  }
  if ($offen<81) {
    $FORM{'level'}='guess';
    digits();
    for ($i=1;$i<=81;$i++) {
      proper($i) if @puzzle[$i] eq "";
    }
    konsistenz() if $fehler==0;
  }
}

my ($host, $DIR1, $DIR2, $DIR3, $DIR4);
$host = hostname();
if ($host eq "fptchlx03.tu-graz.ac.at" ) {
  $DIR1 = "/var/www/script";
  $DIR3 = "../qwdpublic/";
  $mailprog = ">>".$DIR1."/garbage";
} elsif ($host eq "qwd" ) {
  $DIR1 = ".";
  $DIR3 = "../qwd/";
  $mailprog = ">".$DIR1."/garbage";
} else {
  $DIR1 = ".";
  $DIR3 = "/";
  $mailprog = '| /usr/lib/sendmail -t';
}

print "<html>\n";
print "<head>\n";
print "<title>Online Sudoku Help</title>\n";
print '<link rel="SHORTCUT ICON" href="',$DIR3,'favicon.ico" />',"\n";
print '<style type="text/css">',"\n";
print "<!--\n";
print "ul, .col, body {font-family: Sans-Serif; line-height: 100% }\n";
print ".ind {line-height: 130%; margin-left: 1%; margin-right: 5%}\n";
# print "input {font-size: 16px}\n";
print "p {line-height: 120%; margin-left: 3%; margin-right: 8%}\n";
print "ul {line-height: 150%}\n";
print "h4 {margin-left: 33%; margin-right: 5%; font-family: Sans-Serif}\n";
print "h2 {font-size: 32px; font-family: Sans-Serif}\n";
print "h5 {line-height: 170%; font-family: Sans-Serif}\n";
print ".back {background-color: #FFCC66; font-family: Sans-Serif}\n";
print "a:hover {color: rgb(0,0,128)}\n";
print "-->\n";
print "</style>\n";
if ($FORM{'mode'} eq "de") {
  print '<link rel="alternate" type="text/html" title=" " ';
  print 'hreflang="en" href="/cgi-bin/sudoku-doktor.pl?lang=en" />';
} else {
  print '<link rel="alternate" type="text/html" title=" " ';
  print 'hreflang="de" href="/cgi-bin/sudoku-doktor.pl?lang=de" />';
}
print "</head>\n";
print '<body bgcolor="#ffffcc" text="black" link="#0066cc" ';
print 'vlink="#006666" alink="red" ';
print 'background="'.$DIR3.'design.png">';
#print 'length=',$length,"<br />\n";
print '<img src="'.$DIR3.'qwd.gif" hspace="20" align="left" width="89" ';
print 'height="31" vspace="6" alt="" border="0" /> ';
print '<script type="text/javascript" language="Javascript">',"\n";
print '<!--',"\n";
print "document.write('";
print '<a href="http://firmena-z.wko.at/ecg.asp?mg=5238599"><img ';
print "');\n";
print "document.write('";
print 'vspace="6" border="0" src="'.$DIR3.'ecg.gif" ';
print "');\n";
print "document.write('";
print 'height="43" width="89" hspace="20" ';
print "');\n";
print "document.write('";
print 'alt="Informations required by Austrian law." ';
print "');\n";
print "document.write('";
print 'align="right" /></a>';
print "');\n";
print "// -->\n";
print "</script>\n";

print '<h2 align="center" lang="en">';
print '<img src="'.$DIR3.'quality.gif" width="300" height="34" ';
print 'alt="Quality Web Design." /></h2>';
print '<div align="center">';

print '<h5>Univ.-Doz. Dr. Michael Ramek, Laimburggasse&nbsp;26, ';
print '8010&nbsp;Graz, ';
if ($FORM{'lang'} eq "de") {
  print "&Ouml;sterreich";
} else {
  print 'Austria';
}
print '<font color="#ffffcc">.</font></h5>';

print '<img src="'.$DIR3.'1x1009.gif" height="1" width="45%" alt="" /><br />';
#print '<img src="'.$DIR3.'1x1trn.gif" height="32" width="1" alt="" />';
if ($FORM{'step'} eq "") {
  print '<table align="right"><tr lang="en"><td nowrap><img src="',$DIR3;
  if ($FORM{'lang'} eq "de") {
    print 'englisch.gif" width="25" height="13" alt="Switch to" />&nbsp;<a ';
    print 'href="/cgi-bin/sudoku-doktor.pl?lang=en">English version';
  } else {
    print 'deutsch.gif" width="24" height="12" alt="Umschalten auf" />&nbsp;<a ';
    print 'href="/cgi-bin/sudoku-doktor.pl?lang=de">deutsche Version';
  }
  print "</a>.</td></tr></table>\n";
}
print '<br /><h3>Sudoku-Doktor<font color="#ffffcc">.</font></h3>';

if ($FORM{'step'} eq "") {
  for ($i=1;$i<=81;$i++) {
    @puzzle[$i]='';
    $FORM{'p'.$i}='';
  }
  $offen=81;
  if ($FORM{'lang'} eq "de") {
    $msg="Eingabe:" 
  } else {
    $msg="Input:" 
  }
  $FORM{'step'}=1;
  goto unmoeglich;
} else {
  if ($FORM{'lang'} eq "de") {
    $msg="L&ouml;sung:" 
  } else {
    $msg="Solution:" 
  }
  $FORM{'step'}++;
}

if ($fehler==0) {
# print "vor solve<br />\n";
  $offen=solve();
# print "nach solve offen=$offen<br />\n";
  if ($improper>0) {
    if ($FORM{'lang'} eq "de") {
      $msg="(Es gibt keine L&ouml;sung)";
    } else {
      $msg="(No solution possible)";
    }
    $fehler=1;
    goto unmoeglich;
  }
}
if ($fehler==0) {
#  if ($FORM{'lang'} eq "de") {
#    $msg="(durch konsequente Logik)";
#  } else {
#    $msg = "(by means of logic)";
#  }
  if ($offen>0) {
    goto fertig if ($FORM{'level'} eq "stepwize" || $FORM{'level'} eq "logic");
#    $msg="";
    $guess=1;
    @save=@puzzle;
    for ($try=1;$try<=81;$try++) {
      if (@save[$try] eq '') {
        @hinter[$try]="666680";
      }
    }
    $f=0;
    for ($try=1;$try<=81;$try++) {
      if (@save[$try] eq '') {
#        print "<br />probe pos $try\n";
        for ($j=1;$j<=9;$j++) {
#          print "j=$j \n";
          @puzzle[$try]=$j;
          konsistenz();
          if ($fehler==0) {
            $offen=solve(); 
            if ($fehler==0 && $offen==0) {
              $f++;
#             print "f=$f \n";
              @hinter[$try]="0000ff";
              if ($f==1) {
                @solved=@puzzle;
#                if ($FORM{'lang'} eq "de") {
#                  $msg="(einmal Raten notwendig)";
#                } else {
#                  $msg="(one guess necessary)";
#                }
                if ($FORM{'level'} eq 'guess') {goto fertig}
              } else {
                for ($h=1;$h<=81;$h++) { 
                  if (@puzzle[$h]!=@solved[$h]) {
                    $fehler=1;
#                   print "fehler=$fehler\n";
                    for ($f=1;$f<=81;$f++) { @hinter[$f]="ffffff"; }
                    @puzzle=@save;
                    if ($FORM{'lang'} eq "de") {
                      $msg="(mehr als eine L&ouml;sung)";
                    } else {
                      $msg="(more than one solution)";
                    }
                    @bgcolor[1]="cc0000"; 
                    @bgcolor[10]="cc0000"; 
                    @bgcolor[19]="cc0000"; 
                    @bgcolor[28]="cc0000"; 
                    @bgcolor[37]="cc0000"; 
                    @bgcolor[46]="cc0000"; 
                    @bgcolor[55]="cc0000";
                    @bgcolor[64]="cc0000";
                    @bgcolor[73]="cc0000";
                    goto fertig;
                  }
                }
              }
            }
          }
          @puzzle=@save;
        }
      }
    }
    @puzzle=@solved if $f>0;
    konsistenz();
  } 
  fertig:
  $offen=0;
  for ($f=1;$f<=81;$f++) { $offen++ if @puzzle[$f] eq ""; }
#  $msg="&nbsp;" if $offen==0;
# print "<br />fertig: fehler=$fehler offen=$offen\n";
}
if ($offen>0) {
  @bgcolor[1]="cc0000"; 
  @bgcolor[10]="cc0000"; 
  @bgcolor[19]="cc0000"; 
  @bgcolor[28]="cc0000"; 
  @bgcolor[37]="cc0000"; 
  @bgcolor[46]="cc0000"; 
  @bgcolor[55]="cc0000";
  @bgcolor[64]="cc0000";
  @bgcolor[73]="cc0000";
  $fehler=1;
  goto unmoeglich;
}

print "\n";
print '<script language="Javascript" type="text/javascript">',"\n";
print "<!-- \n";
print "function p(n) {\n";
for ($f=1;$f<=81;$f++) {
  print 'if (n=='.$f.') {document.b'.$f.'.src="'.$DIR3.@puzzle[$f].'g.gif";}';
}
print "}\n";
print "// -->\n";
print "</script>\n";

unmoeglich:
print '<form method="post" action="../cgi-bin/sudoku-doktor.pl#anfang">';
print '<input type="hidden" name="lang" value="'.$FORM{'lang'}.'" />';
print '<table width="90%" border="0">';
print '<tr><td valign="top">';
if ($FORM{'lang'} eq "de") {
  print "<p>Korrekt gel&ouml;ste Sudokus enthalten alle Zahlen von \n";
  print "1 bis 9 in jeder Spalte, jeder Zeile und in jedem 3&times;3 ";
  print "Quadrat jeweils genau einmal.</p>\n";
  print '<p>Sind Sie auf halbem Weg stecken geblieben? ';
  print 'Der <b>Sudoku-Doktor</b> hilft rasch und unb&uuml;rokratisch!</p>';
  print '<p>Einfach die bereits bekannten Zahlen in die entsprechenden Felder ';
  print 'einsetzen und danach auf "Help" klicken. Dann in ein ';
  print 'leeres Feld klicken, und es erscheint die richtige L&ouml;sung f&uuml;r dieses Feld!</p>';
  print '<noscript><p><a href="#anfang">Weiter</a>.</p></noscript>';
} else {
  print "<p>Correctly solved Sudoku puzzles contain each digit from ";
  print "1 to 9 in every column, every row, and every 3&times;3 square.</p>\n";
  print '<p>Got stuck in your sudoku puzzle? ';
  print '<b>Sudoku-Doktor</b> is here to help!</p>';
  print '<p>First, insert all known numbers in the proper fields and ';
  print 'click "Help". Second, click into an empty field to get the ';
  print 'correct number for that field!</p>';
  print '<noscript><p><a href="#anfang">Continue</a>.</p></noscript>';
}
print '</td><td rowspan="2" width="45%" align="center">';

print '<table border="0" cellpadding="0" cellspacing="1" bgcolor="';
if ($fehler==0) {
  print '#000099">';
} else {
  print '#cc0000">';
}
print '<tr><th colspan="13"><font color="white"><a name="anfang">';
if ($fehler==0) {
  print $msg;
} else {
  if ($FORM{'lang'} eq "de") {
    print 'Eingabefehler';
  } else {
    print 'Input Error';
  }
  $FORM{'step'}=1;
  $FORM{'submit'}='Error';
}
print '</a></font></th></tr>';
print '<tr><td colspan="13"><img src="'.$DIR3.'1x1trn.gif" width="1" ';
print 'height="1" alt="+-------+-------+-------+" /></td></tr>';
print '<tr>';
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(1); feld(2); feld(3);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(10); feld(11); feld(12);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(19); feld(20); feld(21);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
print '</tr>';
print '<tr>';
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(4); feld(5); feld(6);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(13); feld(14); feld(15);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(22); feld(23); feld(24);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
print '</tr>';
print '<tr>';
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(7); feld(8); feld(9);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(16); feld(17); feld(18);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(25); feld(26); feld(27);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
print '</tr>';
print '<tr><td colspan="13"><img src="'.$DIR3.'1x1trn.gif" width="1" ';
print 'height="1" alt="+-------+-------+-------+" /></td></tr>';
print '<tr>';
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(28); feld(29); feld(30);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(37); feld(38); feld(39);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(46); feld(47); feld(48);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
print '</tr>';
print '<tr>';
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(31); feld(32); feld(33);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(40); feld(41); feld(42);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(49); feld(50); feld(51);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
print '</tr>';
print '<tr>';
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(34); feld(35); feld(36);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(43); feld(44); feld(45);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(52); feld(53); feld(54);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
print '</tr>';
print '<tr><td colspan="13"><img src="'.$DIR3.'1x1trn.gif" width="1" ';
print 'height="1" alt="+-------+-------+-------+" /></td></tr>';
print '<tr>';
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(55); feld(56); feld(57);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(64); feld(65); feld(66);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(73); feld(74); feld(75);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
print '</tr>';
print '<tr>';
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(58); feld(59); feld(60);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(67); feld(68); feld(69);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(76); feld(77); feld(78);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
print '</tr>';
print '<tr>';
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(61); feld(62); feld(63);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(70); feld(71); feld(72);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
feld(79); feld(80); feld(81);
print '<td><img src="'.$DIR3.'1x1trn.gif" width="1" height="1" alt=" | " /></td>';
print '</tr>';
print '<tr><td colspan="13"><img src="'.$DIR3.'1x1trn.gif" width="1" ';
print 'height="1" alt="+-------+-------+-------+" /></td></tr>';
print '</td></tr>';
print '</table>';

print '&nbsp;<br />';
if ($FORM{'step'}==1) {
  print '<input type="submit" name="submit" value="Help" />';
} elsif ($FORM{'step'}==2) {
  print '<input type="submit" name="submit" value="';
  if ($FORM{'lang'} eq 'de') {
    print 'Komplette L&ouml;sung zeigen';
  } else {
    print 'Show complete solution';
  }
  print '" />';
} else {
  print '<input type="submit" name="submit" value="';
  if ($FORM{'lang'} eq 'de') {
    print 'Neues R&auml;tsel';
  } else {
    print 'New puzzle';
  }
  print '" />';
}
print "</td></tr>\n";
print '<tr><td valign="bottom">';
if ($FORM{'submit'} eq "Help") {
  print '<img border="0" type="image/png" ';
  print 'src="http://www.qwd.biz/cgi-bin/zaehler?code=qwd1" ';
  print 'hspace="15" width="89" height="31" alt="" />';
}
print "</td></tr></table>\n";
print '<script language="Javascript">',"\n";
print "<!--\n";
print "document.write('";
print '<input type="hidden" name="step" value="';
if ($FORM{'step'}!=3) {
  print $FORM{'step'};
}
print '" />';
print "');\n";
print "// -->\n";
print "</script>\n";
print "<noscript>\n";
print '<input type="hidden" name="step" value="';
if ($FORM{'step'}!=3) {
  print "2";
}
print '" />';
print "</noscript>\n";
print "</form>\n";
print "&nbsp;<br />\n";
print "<p><b>QWD \n";
if ($FORM{'lang'} eq "de") {
  print 'bietet ma&szlig;geschneiderte ';
  print 'L&ouml;sungen f&uuml;r <a href="http://www.qwd.at/">Homepages</a> ';
  print 'und&nbsp;<a href="http://www.qwd.biz">Online-Applikationen</a>.';
} else {
  print 'offers custom-made ';
  print 'solutions for <a href="http://www.qwd.at/">homepages</a> ';
  print 'and&nbsp;<a href="http://www.qwd.biz">online applications</a>.';
}
print "</b></p>\n";
print "</div>\n";
print "<noscript>\n";
print '<p><a href="http://firmena-z.wko.at/ecg.asp?mg=5238599">';
if ($FORM{'lang'} ne "de") {
  print "Informations required by Austrian law -- ";
}
print 'Informationspflichten ';
print 'laut E-Commerce-Gesetz (ECG) und Mediengesetz.</a></p>',"\n";
print "</noscript>\n";
print "</body>\n";
print "</html>\n";

exit;

sub  solve() {
  $reason=0;
  my ($i,$j,$paar,$old,$sqr,$k,$m,@mgl,$n,$offen,$ii);
  if ($ascii>0) {
    print "\n-----solve----\n";
    for ($i=0;$i<=55;$i=$i+27) {
        printpuzzle(1+$i); printpuzzle(2+$i); printpuzzle(3+$i);    print " ";
        printpuzzle(10+$i); printpuzzle(11+$i); printpuzzle(12+$i); print " ";
        printpuzzle(19+$i); printpuzzle(20+$i); printpuzzle(21+$i); print "\n";
        printpuzzle(4+$i); printpuzzle(5+$i); printpuzzle(6+$i);    print " ";
        printpuzzle(13+$i); printpuzzle(14+$i); printpuzzle(15+$i); print " ";
        printpuzzle(22+$i); printpuzzle(23+$i); printpuzzle(24+$i); print "\n";
        printpuzzle(7+$i); printpuzzle(8+$i); printpuzzle(9+$i);    print " ";
        printpuzzle(16+$i); printpuzzle(17+$i); printpuzzle(18+$i); print " ";
        printpuzzle(25+$i); printpuzzle(26+$i); printpuzzle(27+$i); print "\n\n";
    }
  }
  for ($i=1;$i<=81;$i++) { @moeglich[$i]=" 123456789"; }
  $offen=0;
  for ($i=1;$i<=81;$i++) {
    if (@puzzle[$i] ne "") {
      defpuzzle($i,@puzzle[$i]);
      $offen++;
    }
  }                                   
  print "offen=$offen\n" if $ascii>1;
  if ($lv==0) {
    if ($offen>39) {
      $lv=1;
    } elsif ($offen>35) {
      $lv=2;
    } elsif ($offen>31) {
      $lv=3;
    } elsif ($offen>28) {
      $lv=4;
    } else {
      $lv=5;
    }
  }
  print "lv=$lv\n" if $ascii>1;
  $count=0;
  do {
    my (@anfang)=@moeglich;
    $count++;
    $lv++;
    $neu=0;
    if ($ascii>0) {
      print "\n----- Begin cycle ---- lv=$lv neu=$neu \n";
      printmoeglichkeiten();
    }

# any single (or null) choices?
nochmals:
    for ($i=1;$i<=81;$i++) {
      $j=@moeglich[$i];
      $j =~ s- --g;
      if ($j eq '') {
        $improper=1;
        return -1;
      }
      if ($j<=9 && @puzzle[$i] eq '') {
        $reason=1;
        defpuzzle($i,$j);
        $neu++;
        goto skip if $FORM{'level'} eq "stepwize";
        goto nochmals;
      }
    }
    if ($ascii>0) {
      print "\n----- After phase 1  neu=$neu ----\n";
      printmoeglichkeiten();
    }
    for ($m=1;$m<=9;$m++) {
      $reason=2;
      einzigrow(1,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigrow(4,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigrow(7,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigrow(28,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigrow(31,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigrow(34,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigrow(55,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigrow(58,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigrow(61,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      $reason=3;
      einzigcol(1,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigcol(2,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigcol(3,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigcol(10,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigcol(11,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigcol(12,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigcol(19,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigcol(20,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigcol(21,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      $reason=4;
      einzigsqu(1,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigsqu(10,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigsqu(19,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigsqu(28,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigsqu(37,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigsqu(46,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigsqu(55,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigsqu(64,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
      einzigsqu(73,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
    }                   
    if ($ascii>0) {
      print "\n----- After phase 2 neu=$neu ----\n";
      printmoeglichkeiten();
    }

    $reason=0;
# check every free space for single/double solutions
    $old=$neu;
    for ($i=1;$i<=81;$i++) {
      if (@puzzle[$i]*1>9) {
        $improper=1;
#        print "IMPROPER";
        return 0;
      }
    }
    if ($ascii>0) {
      print "-----  Paerchen: neu=$neu count=$count----\n";
      printmoeglichkeiten();
    }
    if ($neu==0) {
       $reason=5;
       paarcol(1); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarcol(2); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarcol(3); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarcol(10); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarcol(11); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarcol(12); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarcol(19); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarcol(20); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarcol(21); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       print "(7a) neu=$neu\n" if $ascii>0;
       printmoeglichkeiten() if $ascii>0;
    }
    $level="difficult" if ($neu>$old && $level ne "very difficult");
    if ($neu==0) {
       $reason=6;
       paarrow(1); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarrow(4); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarrow(7); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarrow(28); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarrow(31); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarrow(34); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarrow(55); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarrow(58); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarrow(61); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       print "(7b) neu=$neu\n" if $ascii>0;
       printmoeglichkeiten() if $ascii>0;
    }
    $level="difficult" if ($neu>$old && $level ne "very difficult");
    if ($neu==0) {
       $reason=7;
       paarsqu(1); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarsqu(10); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarsqu(19); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarsqu(28); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarsqu(37); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarsqu(46); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarsqu(55); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarsqu(64); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       paarsqu(73); goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
       print "(7c) neu=$neu\n" if $ascii>0;
    }
    $level="difficult" if ($neu>$old && $level ne "very difficult");

# doppelzeilenlogik

    $offen=0;
    for ($i=1;$i<=81;$i++) { $offen++ if @puzzle[$i] eq ''; }

    $reason=8;
    if ($offen>0 && $neu==0) {
      $level="very difficult";
      if ($ascii>0) {
        print "\n---- Ende reg Zyklus - offen=$offen ----\n";
        printmoeglichkeiten();
      }
# check for a square in which a number is restricted to a single column
      
      @mgl=@moeglich;
      $n=" "x10;
      for ($j=1;$j<=9;$j++) {
        for ($sqr=1;$sqr<81;$sqr=$sqr+9) {
          $i=testcol($sqr,$j);
          if ($i>0) {
            print "$j may occur only in col $i of subfield $sqr\n" if $ascii>0;
            $k=$sqr+$i-1;
            $m=$k;
            $m=$m-27 if $m>27;
            $m=$m-27 if $m>27;
            if ($m!=$k) {
              substr(@moeglich[$m],$j,1)=' ';
              substr(@moeglich[$m+3],$j,1)=' ';
              substr(@moeglich[$m+6],$j,1)=' ';
            }
            $m=$m+27;
            if ($m!=$k) {
              substr(@moeglich[$m],$j,1)=' ';
              substr(@moeglich[$m+3],$j,1)=' ';
              substr(@moeglich[$m+6],$j,1)=' ';
            }
            $m=$m+27;
            if ($m!=$k) {
              substr(@moeglich[$m],$j,1)=' ';
              substr(@moeglich[$m+3],$j,1)=' ';
              substr(@moeglich[$m+6],$j,1)=' ';
            }
          }
        }
        for ($sqr=1;$sqr<81;$sqr=$sqr+9) {
          $i=testrow($sqr,$j);
          if ($i>0) {
            print "$j may occur only in row $i of subfield $sqr\n" if $ascii>0;
            $k=$sqr+($i-1)*3;
            $m=$k%9 + (int($k/27))*27;
            if ($m!=$k) {
              substr(@moeglich[$m],$j,1)=' ';
              substr(@moeglich[$m+1],$j,1)=' ';
              substr(@moeglich[$m+2],$j,1)=' ';
            }
            $m=$m+9;
            if ($m!=$k) {
              substr(@moeglich[$m],$j,1)=' ';
              substr(@moeglich[$m+1],$j,1)=' ';
              substr(@moeglich[$m+2],$j,1)=' ';
            }
            $m=$m+9;
            if ($m!=$k) {
              substr(@moeglich[$m],$j,1)=' ';
              substr(@moeglich[$m+1],$j,1)=' ';
              substr(@moeglich[$m+2],$j,1)=' ';
            }
          }
        }
        if ($ascii>0) {
          print "--- end of loop $j ----\n";
          printmoeglichkeiten();
        }
        for ($i=1;$i<=81;$i++) {
          $m=@moeglich[$i];
          $m=~s- --g;
          if ($m<=9 && @puzzle[$i] eq '') {
#            print "Gefunden: $m auf Pos. $i\n" if $ascii>0;
            defpuzzle ($i, $m);
            $neu++;
            return if $FORM{'level'} eq 'stepwize';
          }
        }
      }
      for ($i=1;$i<=81;$i++) {
#        print "i=$i:\n" if $ascii>1;
        if (@mgl[$i]!=@moeglich[$i]) {
          $m=@moeglich[$i];
          $m=~s- -0-g;
          @mgl[$i]=~s- -0-g;
          $m=@mgl[$i]-$m;
          $m=~s-0--g;
#          print "m=$m:\n" if $ascii>1;
          substr($n,$m,1)=$m if ($m>0 && $m<=9);
        }
      }
      $n=~s- --g;
      if ($n>0) {
        if ($ascii>0) {
          print "--- we have a new situation regarding $n ----\n";
          printmoeglichkeiten();
        }
      }
      $m=$n%10;
      while ($m>0) {
        $reason=9;
        einzigrow(1,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
        einzigrow(4,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
        einzigrow(7,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
        einzigrow(28,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
        einzigrow(31,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
        einzigrow(34,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
        einzigrow(55,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
        einzigrow(58,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
        einzigrow(61,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
        $reason=10;
        einzigcol(1,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
        einzigcol(2,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
        einzigcol(3,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
        einzigcol(10,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
        einzigcol(11,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
        einzigcol(12,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
        einzigcol(19,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
        einzigcol(20,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
        einzigcol(21,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
         $reason=11;
         einzigsqu(1,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
         einzigsqu(10,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
         einzigsqu(19,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
         einzigsqu(28,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
         einzigsqu(37,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
         einzigsqu(46,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
         einzigsqu(55,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
         einzigsqu(64,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
         einzigsqu(73,$m); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
        $n=int(($n-$m)/10);
        $m=$n%10;
      }
      if ($ascii>0) {
        print "\n----- danach ----\n";
        printmoeglichkeiten();
      }
    }
    print "neu(1)=$neu\n" if $ascii>0;
    $offen=0;
    for ($i=1;$i<=81;$i++) {$offen++ if @puzzle[$i] eq ''; }
    if ($offen>0) {
      $reason=12;
      for ($j=1;$j<=9;$j++) {
        for ($sqr=1;$sqr<=19;$sqr=$sqr+9) {
          @mgl[1]=doppelcoltest($j,$sqr);
          @mgl[2]=doppelcoltest($j,$sqr+27);
          @mgl[3]=doppelcoltest($j,$sqr+54);
          $n=0;
          if (@mgl[1]==@mgl[2]) {$n=$sqr+54; $i=@mgl[1]}
          if (@mgl[3]==@mgl[2]) {$n=$sqr; $i=@mgl[2]}
          if (@mgl[1]==@mgl[3]) {$n=$sqr+27; $i=@mgl[1]}
          if ($i>0 && $n>0) {
            $spalt2=$i%10;
            $spalt1=($i-$spalt2)/10;
            print "Suche nach $j: kann nicht sein in Quadrat($n), Spalten $i\n" if $ascii>0;
            if ($i<20) {
              substr(@moeglich[$n],$j,1)=' ';
              substr(@moeglich[$n+3],$j,1)=' ';
              substr(@moeglich[$n+6],$j,1)=' ';
            }
            if ($i%10==3) {
              substr(@moeglich[$n+2],$j,1)=' ';
              substr(@moeglich[$n+5],$j,1)=' ';
              substr(@moeglich[$n+8],$j,1)=' ';
            }
            $i=~s/1//;
            $i=~s/3//;
            if ($i==2) {
              substr(@moeglich[$n+1],$j,1)=' ';
              substr(@moeglich[$n+4],$j,1)=' ';
              substr(@moeglich[$n+7],$j,1)=' ';
            }
          }
        }
        if ($ascii>0) {
          print "\n----- danach ----\n";
          printmoeglichkeiten();
        }
        for ($i=1;$i<=81;$i++) {
          if (@puzzle[$i] eq '') {
            $k=@moeglich[$i];
            $k=~s- --g;
            if ($k>0 && $k<=9) {
              defpuzzle($i,$k);
              $neu++;
              $mehrzahl=$j;
              goto skip if($FORM{'level'} eq 'stepwize');
            }
          }
        }
      }
      $reason=20;
      for ($j=1;$j<=9;$j++) {
        for ($sqr=1;$sqr<=81;$sqr=$sqr+27) {
          @mgl[1]=doppelrowtest($j,$sqr);
          @mgl[2]=doppelrowtest($j,$sqr+9);
          @mgl[3]=doppelrowtest($j,$sqr+18);
          $n=0;
          if (@mgl[1]==@mgl[2]) {$n=$sqr+18; $i=@mgl[1]}
          if (@mgl[3]==@mgl[2]) {$n=$sqr; $i=@mgl[2]}
          if (@mgl[1]==@mgl[3]) {$n=$sqr+9; $i=@mgl[1]}
          if ($i>0 && $n>0) {
            print "Suche nach $j: kann nicht sein in Quadrat($n), Zeilen $i\n" if $ascii>0;
            if ($i<20) {
              substr(@moeglich[$n],$j,1)=' ';
              substr(@moeglich[$n+1],$j,1)=' ';
              substr(@moeglich[$n+2],$j,1)=' ';
            }
            if ($i%10==3) {
              substr(@moeglich[$n+6],$j,1)=' ';
              substr(@moeglich[$n+7],$j,1)=' ';
              substr(@moeglich[$n+8],$j,1)=' ';
            }
            $i=~s/1//;
            $i=~s/3//;
            if ($i==2) {
              substr(@moeglich[$n+3],$j,1)=' ';
              substr(@moeglich[$n+4],$j,1)=' ';
              substr(@moeglich[$n+5],$j,1)=' ';
            }
          }
        }
        if ($ascii>0) {
          print "\n----- danach ----\n";
          printmoeglichkeiten();
        }
        for ($i=1;$i<=81;$i++) {
          if (@puzzle[$i] eq '') {
            $k=@moeglich[$i];
            $k=~s- --g;
            if ($k>0 && $k<=9) {
              defpuzzle($i,$k);
              $neu++;
              $mehrzahl=$j;
              goto skip if($FORM{'level'} eq 'stepwize');
            }
          }
        }
      }
      $offen=0;
      for ($i=1;$i<=81;$i++) {$offen++ if @puzzle[$i] eq ''; }
    }
    print "offen: $offen neu: $neu\n" if $ascii>1;        
    if ($neu==0 && $offen>0) {
      my (@dual)=(' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10);
      $i=dualcol( 1, 4, 7,28,31,34,55,58,61); @dual[1]=$i; $i =~ s/ //g; $neu++ if $i>0; print "neu=$neu\n" if $ascii>0;
      $i=dualcol( 2, 5, 8,29,32,35,56,59,62); @dual[2]=$i; $i =~ s/ //g; $neu++ if $i>0; print "neu=$neu\n" if $ascii>0;
      $i=dualcol( 3, 6, 9,30,33,36,57,60,63); @dual[3]=$i; $i =~ s/ //g; $neu++ if $i>0; print "neu=$neu\n" if $ascii>0;
      $i=dualcol(10,13,16,37,40,43,64,67,70); @dual[4]=$i; $i =~ s/ //g; $neu++ if $i>0; print "neu=$neu\n" if $ascii>0;
      $i=dualcol(11,14,17,38,41,44,65,68,71); @dual[5]=$i; $i =~ s/ //g; $neu++ if $i>0; print "neu=$neu\n" if $ascii>0;
      $i=dualcol(12,15,18,39,42,45,66,69,72); @dual[6]=$i; $i =~ s/ //g; $neu++ if $i>0; print "neu=$neu\n" if $ascii>0;
      $i=dualcol(19,22,25,46,49,52,73,76,79); @dual[7]=$i; $i =~ s/ //g; $neu++ if $i>0; print "neu=$neu\n" if $ascii>0;
      $i=dualcol(20,23,26,47,50,53,74,77,80); @dual[8]=$i; $i =~ s/ //g; $neu++ if $i>0; print "neu=$neu\n" if $ascii>0;
      $i=dualcol(21,24,27,48,51,54,75,78,81); @dual[9]=$i; $i =~ s/ //g; $neu++ if $i>0; print "neu=$neu\n" if $ascii>0;
      if ($ascii>0 && $neu>0) {
        print "dual (col): ";
        print @dual[1].'-';
        print @dual[2].'-';
        print @dual[3].' | ';
        print @dual[4].'-';
        print @dual[5].'-';
        print @dual[6].' | ';
        print @dual[7].'-';
        print @dual[8].'-';
        print @dual[9],"\n";
        print "----- nach dual: ----\n";
        printmoeglichkeiten();
      }
    }
    if ($neu==0 && $offen>0) {
      my (@dual)=(' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10);
      $i=dualcol( 1, 2, 3,10,11,12,19,20,21); @dual[1]=$i; $i =~ s/ //g; $neu++ if $i>0;  print "neu=$neu\n" if $ascii>0;
      $i=dualcol( 4, 5, 6,13,14,15,22,23,24); @dual[2]=$i; $i =~ s/ //g; $neu++ if $i>0;  print "neu=$neu\n" if $ascii>0;
      $i=dualcol( 7, 8, 9,16,17,18,25,26,27); @dual[3]=$i; $i =~ s/ //g; $neu++ if $i>0;  print "neu=$neu\n" if $ascii>0;
      $i=dualcol(28,29,30,37,38,39,46,47,48); @dual[4]=$i; $i =~ s/ //g; $neu++ if $i>0;  print "neu=$neu\n" if $ascii>0;
      $i=dualcol(31,32,33,40,41,42,49,50,51); @dual[5]=$i; $i =~ s/ //g; $neu++ if $i>0;  print "neu=$neu\n" if $ascii>0;
      $i=dualcol(34,35,36,43,44,45,52,53,54); @dual[6]=$i; $i =~ s/ //g; $neu++ if $i>0;  print "neu=$neu\n" if $ascii>0;
      $i=dualcol(55,56,57,64,65,66,73,74,75); @dual[7]=$i; $i =~ s/ //g; $neu++ if $i>0;  print "neu=$neu\n" if $ascii>0;
      $i=dualcol(58,59,60,67,68,69,76,77,78); @dual[8]=$i; $i =~ s/ //g; $neu++ if $i>0;  print "neu=$neu\n" if $ascii>0;
      $i=dualcol(61,62,63,70,71,72,79,80,81); @dual[9]=$i; $i =~ s/ //g; $neu++ if $i>0;  print "neu=$neu\n" if $ascii>0;
      if ($neu>0) {
        $mehrzahl=0;
        $mehrzahl=1 if @dual[1] ne ' 'x10;
        $mehrzahl=$mehrzahl*10+2 if @dual[2] ne ' 'x10;
        $mehrzahl=$mehrzahl*10+3 if @dual[3] ne ' 'x10;
        $mehrzahl=$mehrzahl*10+4 if @dual[4] ne ' 'x10;
        $mehrzahl=$mehrzahl*10+5 if @dual[5] ne ' 'x10;
        $mehrzahl=$mehrzahl*10+6 if @dual[6] ne ' 'x10;
        $mehrzahl=$mehrzahl*10+7 if @dual[7] ne ' 'x10;
        $mehrzahl=$mehrzahl*10+8 if @dual[8] ne ' 'x10;
        $mehrzahl=$mehrzahl*10+9 if @dual[9] ne ' 'x10;
#        print "mehrzahl=$mehrzahl\n" if $ascii>0;
        if ($mehrzahl>0 && $mehrzahl<=9) {
          $mehrzahl=@dual[$mehrzahl];
#          print "mehrzahl=:$mehrzahl: if $ascii>0\n";
          $i=0;
          for ($j=1; $j<=9; $j++ ) {
            $i=10*$i+$j if substr($mehrzahl,$j,1) ne ' ';
          }
          $mixzahl=$i;
        }
        if ($ascii>0) {
          print "dual (row): "; 
          print @dual[1].'-';   
          print @dual[2].'-';   
          print @dual[3].' | '; 
          print @dual[4].'-';   
          print @dual[5].'-';   
          print @dual[6].' | '; 
          print @dual[7].'-';   
          print @dual[8].'-';   
          print @dual[9],"\n";  
          print "----- nach dual: ----  mixzahl=$mixzahl\n";
          printmoeglichkeiten();
        }
      }
    }
    $reason=0;
    print "tripel:\n" if $ascii>0;
    if ($neu==0 && $offen>0) {
      @dual=(' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10);
      $reason=13;
      $mehrzahl=tripelcol( 1, 4, 7,28,31,34,55,58,61); @dual[1]=$mehrzahl; print "mehrzahl=$mehrzahl\n" if $ascii>0; 
      goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
      $mehrzahl=tripelcol( 2, 5, 8,29,32,35,56,59,62); @dual[2]=$mehrzahl; print "mehrzahl=$mehrzahl\n" if $ascii>0; 
      goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
      $mehrzahl=tripelcol( 3, 6, 9,30,33,36,57,60,63); @dual[3]=$mehrzahl; print "mehrzahl=$mehrzahl\n" if $ascii>0; 
      goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
      $mehrzahl=tripelcol(10,13,16,37,40,43,64,67,70); @dual[4]=$mehrzahl; print "mehrzahl=$mehrzahl\n" if $ascii>0; 
      goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
      $mehrzahl=tripelcol(11,14,17,38,41,44,65,68,71); @dual[5]=$mehrzahl; print "mehrzahl=$mehrzahl\n" if $ascii>0; 
      goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
      $mehrzahl=tripelcol(12,15,18,39,42,45,66,69,72); @dual[6]=$mehrzahl; print "mehrzahl=$mehrzahl\n" if $ascii>0; 
      goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
      $mehrzahl=tripelcol(19,22,25,46,49,52,73,76,79); @dual[7]=$mehrzahl; print "mehrzahl=$mehrzahl\n" if $ascii>0; 
      goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
      $mehrzahl=tripelcol(20,23,26,47,50,53,74,77,80); @dual[8]=$mehrzahl; print "mehrzahl=$mehrzahl\n" if $ascii>0; 
      goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
      $mehrzahl=tripelcol(21,24,27,48,51,54,75,78,81); @dual[9]=$mehrzahl; print "mehrzahl=$mehrzahl\n" if $ascii>0; 
      goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
      if ($ascii>0) {
        print "trpl (col): ";
        print @dual[1].'-';
        print @dual[2].'-';
        print @dual[3].' | ';
        print @dual[4].'-';
        print @dual[5].'-';
        print @dual[6].' | ';
        print @dual[7].'-';
        print @dual[8].'-';
        print @dual[9],"\n";
        print "----- nach tripel: ----\n";
        printmoeglichkeiten();
       }
    }
    if ($neu==0 && $offen>0) {
      @dual=(' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10,' 'x10);
      $reason=14;
      $mehrzahl=tripelcol( 1, 2, 3,10,11,12,19,20,21); @dual[1]=$mehrzahl; print "mehrzahl=$mehrzahl\n" if $ascii>0; 
      goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
      $mehrzahl=tripelcol( 4, 5, 6,13,14,15,22,23,24); @dual[2]=$mehrzahl; print "mehrzahl=$mehrzahl\n" if $ascii>0; 
      goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
      $mehrzahl=tripelcol( 7, 8, 9,16,17,18,25,26,27); @dual[3]=$mehrzahl; print "mehrzahl=$mehrzahl\n" if $ascii>0; 
      goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
      $mehrzahl=tripelcol(28,29,30,37,38,39,46,47,48); @dual[4]=$mehrzahl; print "mehrzahl=$mehrzahl\n" if $ascii>0; 
      goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
      $mehrzahl=tripelcol(31,32,33,40,41,42,49,50,51); @dual[5]=$mehrzahl; print "mehrzahl=$mehrzahl\n" if $ascii>0; 
      goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
      $mehrzahl=tripelcol(34,35,36,43,44,45,52,53,54); @dual[6]=$mehrzahl; print "mehrzahl=$mehrzahl\n" if $ascii>0; 
      goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
      $mehrzahl=tripelcol(55,56,57,64,65,66,73,74,75); @dual[7]=$mehrzahl; print "mehrzahl=$mehrzahl\n" if $ascii>0; 
      goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
      $mehrzahl=tripelcol(58,59,60,67,68,69,76,77,78); @dual[8]=$mehrzahl; print "mehrzahl=$mehrzahl\n" if $ascii>0; 
      goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
      $mehrzahl=tripelcol(61,62,63,70,71,72,79,80,81); @dual[9]=$mehrzahl; print "mehrzahl=$mehrzahl\n" if $ascii>0; 
      goto skip if ($neu>0 && $FORM{'level'} eq "stepwize");
      if ($ascii>0) {
        print "trpl (row): ";
        print @dual[1].'-';
        print @dual[2].'-';
        print @dual[3].' | ';
        print @dual[4].'-';
        print @dual[5].'-';
        print @dual[6].' | ';
        print @dual[7].'-';
        print @dual[8].'-';
        print @dual[9],"\n";
        print "----- nach tripel: ----\n";
        printmoeglichkeiten();
       }
    }
    $reason=0;
    do {
      $offen=0;
      for ($i=1;$i<=81;$i++) {$offen++ if @puzzle[$i] eq ''; }
      $old=$neu;
      if ($offen>0) {
        for ($m=1;$m<=9;$m++) {
          $reason=16;
          einzigrow(1,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigrow(4,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigrow(7,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigrow(28,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigrow(31,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigrow(34,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigrow(55,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigrow(58,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigrow(61,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          $reason=17;
          einzigcol(1,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigcol(2,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigcol(3,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigcol(10,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigcol(11,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigcol(12,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigcol(19,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigcol(20,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigcol(21,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          $reason=18;
          einzigsqu(1,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigsqu(10,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigsqu(19,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigsqu(28,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigsqu(37,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigsqu(46,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigsqu(55,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigsqu(64,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
          einzigsqu(73,$m); goto skip if($neu>$old && $FORM{'level'} eq 'stepwize');
        }
      }
      print "offen= $offen neu= $neu\n" if $ascii>1;        
    } until ($neu==$old);
    $ii=0;
    for ($i=1;$i<=81;$i++) {$ii++ if @anfang[$i] eq @moeglich[$i]; }
    print "ii=$ii offen=$offen count=$count\n" if $ascii>0;
  }
  until ($ii==81 || $offen==0 || $count>9);
  skip:
  konsistenz();
  $offen=0;
  for ($i=1;$i<=81;$i++) {$offen++ if @puzzle[$i] eq ''; }
  if ($ascii>0) {
    print "offen=$offen\n";
    printmoeglichkeiten() if $offen>0;
  }
  return $offen;
}

sub feld() {
 my ($i) = $_[0];
 print '<td height="28" width="28" align="center" bgcolor="#ffffff">';
 my $k=$FORM{'p'.$i};
 print '<input type="';
 if ($fehler>0 || $FORM{'step'}==1 ) {
   print 'text" maxlength="1" size="1" ';
   print 'value="'.$k.'" name="p',$i.$unique.'" />';
 } else {
   print 'hidden" ';
   print 'value="'.$k.'" name="p',$i.$unique.'" />';
   if ($k eq "") {
     print '<a href="javascript:p('.$i.')"><img border="0" src="';
     if ($FORM{'step'}==3) {
       print $DIR3.@puzzle[$i].'g.gif" alt="'.@puzzle[$i];
     } else {
       print $DIR3.'1x1fff.gif" alt=" ';
     }
     print '" name="b'.$i.'" height=28" width="28" /></a>';
   } else {
     print '<img border="0" src="'.$DIR3.$k.'s.gif';
     print '" height=28" width="28" alt="'.$k.'" />';
   }
 }
 print '</td>';
}

sub checkpaerchen() {
  my ($i) = $_[0];
  my ($j,$icol,$jcol,$irow,$jrow,$n1,$n2,$n,$isq,$i1);
  for ($j=$i+1;$j<=81;$j++) {
    if (@paerchen[$i] eq @paerchen[$j]) {
      print "i=$i j=$j @paerchen[$i]\n" if $ascii>0;
      $icol=$i;
      $icol=$icol-27 if $icol>27;
      $icol=$icol-27 if $icol>27;
      $icol=$icol-3 if ($icol>=4 && $icol<=9);
      $icol=$icol-3 if ($icol>=4 && $icol<=6);
      $icol=$icol-3 if ($icol>=13 && $icol<=18);
      $icol=$icol-3 if ($icol>=13 && $icol<=15);
      $icol=$icol-3 if ($icol>=22 && $icol<=27);
      $icol=$icol-3 if ($icol>=22 && $icol<=24);
      $jcol=$j;
      $jcol=$jcol-27 if $jcol>27;
      $jcol=$jcol-27 if $jcol>27;
      $jcol=$jcol-3 if ($jcol>=4 && $jcol<=9);
      $jcol=$jcol-3 if ($jcol>=4 && $jcol<=6);
      $jcol=$jcol-3 if ($jcol>=13 && $jcol<=18);
      $jcol=$jcol-3 if ($jcol>=13 && $jcol<=15);
      $jcol=$jcol-3 if ($jcol>=22 && $jcol<=27);
      $jcol=$jcol-3 if ($jcol>=22 && $jcol<=24);
      $irow=$i;
      $irow=$irow-27 if $irow>54;
      $irow=$irow-27 if $irow>27;
      $irow=$irow-9 if $irow>18;
      $irow=$irow-9 if $irow>9;
      $irow=1 if ($irow==2 || $irow==3);
      $irow=4 if ($irow==5 || $irow==6);
      $irow=7 if ($irow==8 || $irow==9);
      $irow=$irow+27*int(($i-$icol)/27);
      $jrow=$j;
      $jrow=$jrow-27 if $jrow>54;
      $jrow=$jrow-27 if $jrow>27;
      $jrow=$jrow-9 if $jrow>18;
      $jrow=$jrow-9 if $jrow>9;
      $jrow=1 if ($jrow==2 || $jrow==3);
      $jrow=4 if ($jrow==5 || $jrow==6);
      $jrow=7 if ($jrow==8 || $jrow==9);
      $jrow=$jrow+27*int(($j-$jcol)/27);
      $n1=@paerchen[$i];
      $n1 =~ s- --g;
      $n2=int($n1/10);
      $n1=$n1%10;
      $isq=int(($irow-1)/27)*27+1;

      $n=$neu;
 print "icol=$icol jcol=$jcol irow=$irow jrow=$jrow isq=$isq n1=$n1 n2=$n2<br />\n" if $ascii>0;
      if ($irow==$jrow) {
        @puzzle[$i]=$n1;
        @puzzle[$j]=$n2;
        completeline($irow);
        singleline($irow);
# check every free space for single solutions
        $i1=$irow; solitary($i1,2) if @puzzle[$i1] eq "";
        $i1++; solitary($i1,2) if @puzzle[$i1] eq "";
        $i1++; solitary($i1,2) if @puzzle[$i1] eq "";
        $i1=$i1+7; solitary($i1,2) if @puzzle[$i1] eq "";
        $i1++; solitary($i1,2) if @puzzle[$i1] eq "";
        $i1++; solitary($i1,2) if @puzzle[$i1] eq "";
        $i1=$i1+7; solitary($i1,2) if @puzzle[$i1] eq "";
        $i1++; solitary($i1,2) if @puzzle[$i1] eq "";
        $i1++; solitary($i1,2) if @puzzle[$i1] eq "";
        @puzzle[$i]="";
        @puzzle[$j]="";
      }

      if ($icol==$jcol) {
        @puzzle[$i]=$n1;
        @puzzle[$j]=$n2;
        completecolumn($icol);
        singlecolumn($icol);
# check every free space for single solutions
        $i1=$icol; solitary($i1,2) if @puzzle[$i1] eq "";
        $i1=$i1+3; solitary($i1,2) if @puzzle[$i1] eq "";
        $i1=$i1+3; solitary($i1,2) if @puzzle[$i1] eq "";
        $i1=$i1+21; solitary($i1,2) if @puzzle[$i1] eq "";
        $i1=$i1+3; solitary($i1,2) if @puzzle[$i1] eq "";
        $i1=$i1+3; solitary($i1,2) if @puzzle[$i1] eq "";
        $i1=$i1+21; solitary($i1,2) if @puzzle[$i1] eq "";
        $i1=$i1+3; solitary($i1,2) if @puzzle[$i1] eq "";
        $i1=$i1+3; solitary($i1,2) if @puzzle[$i1] eq "";
        @puzzle[$i]="";
        @puzzle[$j]="";
      }
    }
  }
}

sub completesquare() {
 my ($i) = $_[0];
 my ($anzahl)=0;
 my ($summe)=1+2+3+4+5+6+7+8+9;
 my ($k,$j,$n);
 for ($j=$i;$j<$i+9;$j++) {
  $k=@puzzle[$j]*1;
  if ($k>0) {
    $anzahl++; $summe=$summe-$k;
  } else {
    $n=$j;
  }
 }
 if ($anzahl==8) {
   $neu++;
   @puzzle[$n]=$summe;
   print "gefunden $summe pos $n\n" if $ascii>1;
 }
}

sub completecolumn() {
 my ($i) = $_[0];
# print "i=$i " if $ascii>1;
 return if $i>73;
 my ($anzahl)=0;
 my ($summe)=1+2+3+4+5+6+7+8+9;
 my ($k,$j,$n);
 for ($j=1;$j<=3;$j++) {
  $k=@puzzle[$i]*1;
  if ($k>0) {$anzahl++; $summe=$summe-$k;} else {$n=$i;}
  $i=$i+3;
  $k=@puzzle[$i]*1;
  if ($k>0) {$anzahl++; $summe=$summe-$k;} else {$n=$i;}
  $i=$i+3;
  $k=@puzzle[$i]*1;
  if ($k>0) {$anzahl++; $summe=$summe-$k;} else {$n=$i;}
  $i=$i+21;
 }
 if ($anzahl==8) {
   $neu++;
   print "i=$i n=$n neu=$neu\n" if $ascii>1;
   @puzzle[$n]=$summe;
   print "gefunden $summe pos $n\n" if $ascii>1;
 }
}

sub completeline() {
 my ($i) = $_[0];
 my ($anzahl)=0;
 my ($summe)=1+2+3+4+5+6+7+8+9;
 my ($k,$j,$n);
 for ($j=1;$j<=3;$j++) {
  $k=@puzzle[$i]*1;
  if ($k>0) {$anzahl++; $summe=$summe-$k;} else {$n=$i;}
  $i++;
  $k=@puzzle[$i]*1;
  if ($k>0) {$anzahl++; $summe=$summe-$k;} else {$n=$i;}
  $i++;
  $k=@puzzle[$i]*1;
  if ($k>0) {$anzahl++; $summe=$summe-$k;} else {$n=$i;}
  $i=$i+7;
 }
 if ($anzahl==8) {
   $neu++;
   @puzzle[$n]=$summe;
   print "gefunden $summe pos $n\n" if $ascii>1;
 }
}

sub singlesquare() {
 my ($i) = $_[0];
 print "\n singlesquare $i\n" if $ascii==1;
 my ($j,$k,$n,$m,@lokal);
 $n=0;
 for ($j=1;$j<=9;$j++) {
 print "suche nach $j\n" if $ascii==1;
   $n=0;
   for ($k=$i;$k<$i+9;$k++) { $n=1 if @puzzle[$k]==$j; @lokal[$k]=0 }
   if ($n==0) {
     for ($k=$i;$k<$i+9;$k++) {
     print "position $k\n" if $ascii==1;
       @lokal[$k]=1 if @puzzle[$k] ne "";
# lokal[]==1 : $j kann an dieser Stelle nicht sein!
       $n=$k%27;
       $n=21 if ($n==0 || $n==24);
       $n=20 if ($n==23 || $n==26);
       $n=19 if ($n==22 || $n==25);
       $n=10 if ($n==13 || $n==16);
       $n=11 if ($n==14 || $n==17);
       $n=12 if ($n==15 || $n==18);
       $n=1 if ($n==4 || $n==7);
       $n=2 if ($n==5 || $n==8);
       $n=3 if ($n==6 || $n==9);
       print "n=$n\n" if $ascii==1;
#       $n=$i-1+$n;
#       print "n=$n\n" if $ascii==1;
       @lokal[$k]=1 if @puzzle[$n]==$j;
       @lokal[$k]=1 if @puzzle[$n+3]==$j;
       @lokal[$k]=1 if @puzzle[$n+6]==$j;
       @lokal[$k]=1 if @puzzle[$n+27]==$j;
       @lokal[$k]=1 if @puzzle[$n+30]==$j;
       @lokal[$k]=1 if @puzzle[$n+33]==$j;
       @lokal[$k]=1 if @puzzle[$n+54]==$j;
       @lokal[$k]=1 if @puzzle[$n+57]==$j;
       @lokal[$k]=1 if @puzzle[$n+60]==$j;
       $n=$k%27;
       $n=$n%9;
       $n=9 if $n==0;
       $n=1 if $n<=3;
       $n=4 if ($n==5 || $n==6);
       $n=7 if ($n==8 || $n==9);
       $n=$n+27 if $k>27;
       $n=$n+27 if $k>54;
       print "n=$n\n" if $ascii==1;
       @lokal[$k]=1 if @puzzle[$n]==$j;
       @lokal[$k]=1 if @puzzle[$n+1]==$j;
       @lokal[$k]=1 if @puzzle[$n+2]==$j;
       @lokal[$k]=1 if @puzzle[$n+9]==$j;
       @lokal[$k]=1 if @puzzle[$n+10]==$j;
       @lokal[$k]=1 if @puzzle[$n+11]==$j;
       @lokal[$k]=1 if @puzzle[$n+18]==$j;
       @lokal[$k]=1 if @puzzle[$n+19]==$j;
       @lokal[$k]=1 if @puzzle[$n+20]==$j;
     }
     $n=0;
     for ($k=$i;$k<$i+9;$k++) {
       if (@lokal[$k]==0) {
         $n++;
         $m=$k;
       }
     }
     if ($n==1) {
       @puzzle[$m]=$j;
       $neu++ ;
       print "gefunden $j pos $m\n" if $ascii>1;
     }
   }
 }
}

sub singlecolumn() {
 my ($i) = $_[0];
 print "singlecolumn $i\n" if $ascii==1;
 my (@lokal,$j,$k,$n,$m,$l,@pos);
 for ($j=1;$j<=9;$j++) {
   print "suche nach $j\n" if $ascii==1;
   $n=0;
   $k=$i;
   $l=0;
   @lokal=(0,0,0,0,0,0,0,0,0,0);
   for ($m=1;$m<=3;$m++) {
     $l++;
     @lokal[$l]=1 if @puzzle[$k]!="";
     @pos[$l]=$k;
     $n=1 if @puzzle[$k]==$j;
     $k=$k+3;
     $l++;
     @lokal[$l]=1 if @puzzle[$k]!="";
     @pos[$l]=$k;
     $n=1 if @puzzle[$k]==$j;
     $k=$k+3;
     $l++;
     @lokal[$l]=1 if @puzzle[$k]!="";
     @pos[$l]=$k;
     $n=1 if @puzzle[$k]==$j;
     $k=$k+21;
   }
   print "@lokal\n" if $ascii==1;
   if ($n==0) {
     for ($l=1;$l<=9;$l++) {
       $k=@pos[$l];
       $m=$k-$i+1;
       @lokal[$l]=1 if (@puzzle[$m]==$j || @puzzle[$m+1]==$j || @puzzle[$m+2]==$j);
       @lokal[$l]=1 if (@puzzle[$m+9]==$j || @puzzle[$m+10]==$j || @puzzle[$m+11]==$j);
       @lokal[$l]=1 if (@puzzle[$m+18]==$j || @puzzle[$m+19]==$j || @puzzle[$m+20]==$j);
       if ($i<=3) {
         $m=1 if ($m==4 || $m==7);
         $m=28 if ($m==31 || $m==34);
         $m=55 if ($m==58 || $m==61);
       } elsif ($i>=19) {
         $m=19 if ($m==1 || $m==4 || $m==7);
         $m=46 if ($m==28 || $m==31 || $m==34);
         $m=73 if ($m==55 || $m==58 || $m==61);
       } else {
         $m=10 if ($m==1 || $m==4 || $m==7);
         $m=37 if ($m==28 || $m==31 || $m==34);
         $m=64 if ($m==55 || $m==58 || $m==61);
       }
       print "m=$m\n" if $ascii==1;
       for ($n=0;$n<9;$n++) {@lokal[$l]=1 if (@puzzle[$m+$n]==$j);}
     }
     print "@lokal\n" if $ascii==1;
     $n=9;
     for ($l=1;$l<=9;$l++) {
       if (@lokal[$l]==0) {
         $m=@pos[$l]
       } else {
         $n=$n-@lokal[$l]
       }
     }
     if ($n==1) {
       @puzzle[$m]=$j;
       print "gefunden: $j pos $m \n" if $ascii>1;
       $neu++;
     }
   }
 }
}

sub singleline() {
 my ($i) = $_[0];
 print "singleline $i\n" if $ascii==1;
 my (@lokal,$j,$k,$m,$n,$l,@pos);
 for ($j=1;$j<=9;$j++) {
   print "suchen nach $j\n" if $ascii==1;
   $n=0;
   $k=$i;
   $l=0;
   @lokal=(0,0,0,0,0,0,0,0,0,0);
   for ($m=1;$m<=3;$m++) {
     $l++;
     @lokal[$l]=1 if @puzzle[$k]!="";
     @pos[$l]=$k;
     $n=1 if @puzzle[$k]==$j;
     $k++;
     $l++;
     @lokal[$l]=1 if @puzzle[$k]!="";
     @pos[$l]=$k;
     $n=1 if @puzzle[$k]==$j;
     $k++;
     $l++;
     @lokal[$l]=1 if @puzzle[$k]!="";
     @pos[$l]=$k;
     $n=1 if @puzzle[$k]==$j;
     $k=$k+7;
   }
   print "@lokal\n" if $ascii==1;
   if ($n==0) {
     for ($l=1;$l<=9;$l++) {
       $k=@pos[$l];
       $m=$k%27;
       $m=1 if ($m==4 || $m==7);
       $m=2 if ($m==5 || $m==8);
       $m=3 if ($m==6 || $m==9);
       $m=10 if ($m==13 || $m==16);
       $m=11 if ($m==14 || $m==17);
       $m=12 if ($m==15 || $m==18);
       $m=19 if ($m==22 || $m==25);
       $m=20 if ($m==23 || $m==26);
       $m=21 if ($m==24 || $m==0);
       print "m=$m\n" if $ascii==1;
       @lokal[$l]=1 if (@puzzle[$m]==$j || @puzzle[$m+3]==$j || @puzzle[$m+6]==$j); 
       @lokal[$l]=1 if (@puzzle[$m+27]==$j || @puzzle[$m+30]==$j || @puzzle[$m+33]==$j); 
       @lokal[$l]=1 if (@puzzle[$m+54]==$j || @puzzle[$m+57]==$j || @puzzle[$m+60]==$j); 
       $m=1 if ($m<=3);
       $m=19 if ($m>19);
       $m=10 if ($m==11 || $m==12);
       $m=$m+27 if $i>7;
       $m=$m+27 if $i>34;
       print "m = $m\n" if $ascii==1;
       for ($n=0;$n<9;$n++) {@lokal[$l]=1 if (@puzzle[$m+$n]==$j);}
     }
     print "@lokal\n" if $ascii==1;
     $n=9;
     for ($l=1;$l<=9;$l++) {
       if (@lokal[$l]==0) {
         $m=@pos[$l]
       } else {
         $n=$n-@lokal[$l]
       }
     }
     if ($n==1) {
       @puzzle[$m]=$j;
       print "gefunden: $j pos $m \n" if $ascii>1;
       $neu++;
     }
   }
 }
}

sub solitary() {
 my ($k) = $_[0];
 my ($d) = $_[1];
 print "solitary $k $d\n" if $ascii>0;
 my ($m,$l,$j,$n,$i,@pos,$p,$puz,$s,$t);
 $t=$k%9;
 $t=9 if $t==0;
 $t=$k-$t+1;
 $m=$k%27;
 $m=1 if ($m==4 || $m==7);
 $m=2 if ($m==5 || $m==8);
 $m=3 if ($m==6 || $m==9);
 $m=10 if ($m==13 || $m==16);
 $m=11 if ($m==14 || $m==17);
 $m=12 if ($m==15 || $m==18);
 $m=19 if ($m==22 || $m==25);
 $m=20 if ($m==23 || $m==26);
 $m=21 if ($m==24 || $m==0);
 $l=$k%9;
 $l=4 if ($l==5 || $l==6);
 $l=7 if ($l==8 || $l==0);
 $l=1 if $l<4;
 $l=$l+27 if $k>27;
 $l=$l+27 if $k>54;
 print "k=$k m=$m l=$l t=$t\n" if $ascii>0;
 @pos=($t,$t+1,$t+2,$t+3,$t+4,$t+5,$t+6,$t+7,$t+8,$m,$m+3,$m+6,$m+27,$m+30,$m+33,$m+54,$m+57,$m+60,$l,$l+1,$l+2,$l+9,$l+10,$l+11,$l+18,$l+19,$l+20);
 #print "                                         pos=@pos[3]\n" if $ascii>1;
 $n=0;
 for ($j=1; $j<=9; $j++) {
   print "Suche nach $j\n" if $ascii==1;
   for ($p=0;$p<27;$p++) {
     $i=$j;
     $puz=@pos[$p];
     if ($puz!=$k) {
       $puz=@puzzle[$puz];
       print "testing (pos: @pos[$p]) :$puz:\n" if $ascii==1;
       if ($puz ne "") {
         if ($puz*1==$j) {
           $i=0;
           goto solit;
         }
       }
     }
   }
   substr(@paerchen[$k],$j,1)=$j;
   substr(@moeglich[$k],$j,1)=$j;
   solit:
   if ($i==$j) {
     $n++;
     $s=$j;
   }
 }
 print "@moeglich[$k] n=$n\n" if $ascii>0;
 if ($n==0) {
   $improper=1;
   $j=$m%9;
   $i=9 if $j==0;
   $m=$m-$j+1;
   @bgcolor[$m]="cc0000";
   @bgcolor[$m+27]="cc0000";
   @bgcolor[$m+54]="cc0000";
   @bgcolor[$l]="cc0000";
   @bgcolor[$l+9]="cc0000";
   @bgcolor[$l+18]="cc0000";
 } elsif ($n==1) {
   @puzzle[$k]=$s;
   $neu++;
   print "gefunden: $s pos $k \n" if $ascii>0;
 }
 if ($d==1) {
   if ($n==2) {
#     print "k=$k: @paerchen[$k] \n";
   } else {
     @paerchen[$k]=" "x10;
   }
 }
 print "n=$n d=$d\n" if $ascii>0;
}

sub waagrechtsquare() {
 my (@m,@m1,@m2,$j,$n,$n1,$n2,$j1,$j2,$j4,$l1,$l2,$l3);
 my ($k) = $_[0];
 my ($k1)=$k+9;
 my ($k2)=$k+18;
 if ($k%27>1) {$k1 = $k-9; $k2=$k+9}
 if ($k%27>10) {$k2 = $k-18}
 print "waagrechtsquare $k : $k1 $k2<br />\n" if $ascii>0;
 for ($j=1;$j<=9;$j++) {
   @m=('',0,0,0); @m1=('',0,0,0); @m2=(':',0,0,0);
   if (substr(@moeglich[$k],$j,1) eq $j) {@m[1]=$j}
   if (substr(@moeglich[$k+1],$j,1) eq $j) {@m[1]=$j}
   if (substr(@moeglich[$k+2],$j,1) eq $j) {@m[1]=$j}
   if (substr(@moeglich[$k+3],$j,1) eq $j) {@m[2]=$j}
   if (substr(@moeglich[$k+4],$j,1) eq $j) {@m[2]=$j}
   if (substr(@moeglich[$k+5],$j,1) eq $j) {@m[2]=$j}
   if (substr(@moeglich[$k+6],$j,1) eq $j) {@m[3]=$j}
   if (substr(@moeglich[$k+7],$j,1) eq $j) {@m[3]=$j}
   if (substr(@moeglich[$k+8],$j,1) eq $j) {@m[3]=$j}
   if (substr(@moeglich[$k1],$j,1) eq $j) {@m1[1]=$j}
   if (substr(@moeglich[$k1+1],$j,1) eq $j) {@m1[1]=$j}
   if (substr(@moeglich[$k1+2],$j,1) eq $j) {@m1[1]=$j}
   if (substr(@moeglich[$k1+3],$j,1) eq $j) {@m1[2]=$j}
   if (substr(@moeglich[$k1+4],$j,1) eq $j) {@m1[2]=$j}
   if (substr(@moeglich[$k1+5],$j,1) eq $j) {@m1[2]=$j}
   if (substr(@moeglich[$k1+6],$j,1) eq $j) {@m1[3]=$j}
   if (substr(@moeglich[$k1+7],$j,1) eq $j) {@m1[3]=$j}
   if (substr(@moeglich[$k1+8],$j,1) eq $j) {@m1[3]=$j}
   if (substr(@moeglich[$k2],$j,1) eq $j) {@m2[1]=$j}
   if (substr(@moeglich[$k2+1],$j,1) eq $j) {@m2[1]=$j}
   if (substr(@moeglich[$k2+2],$j,1) eq $j) {@m2[1]=$j}
   if (substr(@moeglich[$k2+3],$j,1) eq $j) {@m2[2]=$j}
   if (substr(@moeglich[$k2+4],$j,1) eq $j) {@m2[2]=$j}
   if (substr(@moeglich[$k2+5],$j,1) eq $j) {@m2[2]=$j}
   if (substr(@moeglich[$k2+6],$j,1) eq $j) {@m2[3]=$j}
   if (substr(@moeglich[$k2+7],$j,1) eq $j) {@m2[3]=$j}
   if (substr(@moeglich[$k2+8],$j,1) eq $j) {@m2[3]=$j}
   $n=0;
   $n++ if @m[1]==$j;
   $n++ if @m[2]==$j;
   $n++ if @m[3]==$j;
   $n1=0;
   if (@m1[1]==$j) { $n1++; $j1=1 }
   if (@m1[2]==$j) { $n1++; $j1=2 }
   if (@m1[3]==$j) { $n1++; $j1=3 }
   $n2=0;
   if (@m2[1]==$j) { $n2++; $j2=1 }
   if (@m2[2]==$j) { $n2++; $j2=2 }
   if (@m2[3]==$j) { $n2++; $j2=3 }
#   print "Suche nach $j: @m1 @m2 : $n1 $n2 $n<br />\n";
   if (($n1==1 && $n2==1) && $n!=1) {
#     print "j1,j2= $j1 $j2<br />\n";
     if ($j1==1 || $j2==1) {
       substr(@moeglich[$k],$j,1)=' ';
       substr(@moeglich[$k+1],$j,1)=' ';
       substr(@moeglich[$k+2],$j,1)=' ';
     }
     if ($j1==2 || $j2==2) {
       substr(@moeglich[$k+3],$j,1)=' ';
       substr(@moeglich[$k+4],$j,1)=' ';
       substr(@moeglich[$k+5],$j,1)=' ';
     }
     if ($j1==3 || $j2==3) {
       substr(@moeglich[$k+6],$j,1)=' ';
       substr(@moeglich[$k+7],$j,1)=' ';
       substr(@moeglich[$k+8],$j,1)=' ';
     }
     $l3=0;
     for ($n=1; $n<=9; $n++) {
       if ($n!=$j) {
         $l1=0;
         $l2=0;
         for ($j1=0;$j1<=8;$j1++) {
           $l1++ if (substr(@moeglich[$k+$j1],$j,1)==$j && substr(@moeglich[$k+$j1],$n,1)==$n);
           $l2++ if (substr(@moeglich[$k+$j1],$j,1)!=$j && substr(@moeglich[$k+$j1],$n,1)==$n);
         }
         if ($l1==2 && $l2==0) {
           $l3++;
           $j2=$n;
         }
       }
     }
#     print "l3=$l3<br />\n";
     if ($l3==1) {
#       print "n=$j2<br />\n";
       $l1=0;
       for ($j1=0;$j1<=8;$j1++) {
         if (substr(@moeglich[$k+$j1],$j,1)==$j &&
             substr(@moeglich[$k+$j1],$j2,1)==$j2) {
           if ($l1==0) {$l1=$j1} else {$l2=$j1}
         }
       }
#       print "l1=$l1 l2=$l2<br />\n";
       for ($j1=1;$j1<=9;$j1++) {
         if ($j1!=$j && $j1!=$j2) {
           substr(@moeglich[$k+$l1],$j1,1) =" ";
           substr(@moeglich[$k+$l2],$j1,1) =" ";
         }
       }
#       print "<pre>\n";
#       print "@moeglich[$k] : @moeglich[$k+1] : @moeglich[$k+2]\n"; 
#       print "@moeglich[$k+3] : @moeglich[$k+4] : @moeglich[$k+5]\n"; 
#       print "@moeglich[$k+6] : @moeglich[$k+7] : @moeglich[$k+8]\n"; 
#       print "@moeglich[$k1] : @moeglich[$k1+1] : @moeglich[$k1+2]\n"; 
#       print "@moeglich[$k1+3] : @moeglich[$k1+4] : @moeglich[$k1+5]\n"; 
#       print "@moeglich[$k1+6] : @moeglich[$k1+7] : @moeglich[$k1+8]\n"; 
#       print "@moeglich[$k2] : @moeglich[$k2+1] : @moeglich[$k2+2]\n"; 
#       print "@moeglich[$k2+3] : @moeglich[$k2+4] : @moeglich[$k2+5]\n"; 
#       print "@moeglich[$k2+6] : @moeglich[$k2+7] : @moeglich[$k2+8]\n"; 
#       print "</pre>\n";
       for ($j4=1;$j4<=9;$j4++) {
         $l1=0;
         for ($j2=0;$j2<=8;$j2++) {        
           if (substr(@moeglich[$k+$j2],$j4,1)==$j4) {$l1++; $l3=$j2}
         }
#         print "j4=$j4 l1=$l1 <br />\n";
         if ($l1==1 && @puzzle[$k+$l3] eq "") {
           print "gefunden: $j4 an pos ",$k+$l3,"\n" if $ascii>0;
           @puzzle[$k+$l3]=$j4;
           $neu++;
           return;
         }
       }
     } else {
#       print "<pre>\n";
#       print "@moeglich[$k] : @moeglich[$k+1] : @moeglich[$k+2]\n"; 
#       print "@moeglich[$k+3] : @moeglich[$k+4] : @moeglich[$k+5]\n"; 
#       print "@moeglich[$k+6] : @moeglich[$k+7] : @moeglich[$k+8]\n"; 
#       print "@moeglich[$k1] : @moeglich[$k1+1] : @moeglich[$k1+2]\n"; 
#       print "@moeglich[$k1+3] : @moeglich[$k1+4] : @moeglich[$k1+5]\n"; 
#       print "@moeglich[$k1+6] : @moeglich[$k1+7] : @moeglich[$k1+8]\n"; 
#       print "@moeglich[$k2] : @moeglich[$k2+1] : @moeglich[$k2+2]\n"; 
#       print "@moeglich[$k2+3] : @moeglich[$k2+4] : @moeglich[$k2+5]\n"; 
#       print "@moeglich[$k2+6] : @moeglich[$k2+7] : @moeglich[$k2+8]\n"; 
#       print "</pre>\n";
       for ($j2=0;$j2<=8;$j2++) {        
         $l1=0;
         for ($j4=1;$j4<=9;$j4++) {
           if (substr(@moeglich[$k+$j2],$j4,1)==$j4) {$l1++; $l3=$j4}
         }
#         print "j2=$j2 l1=$l1 <br />\n";
         if ($l1==1 && @puzzle[$k+$j2] eq "") {
           print "gefunden: $l3 an pos ",$k+$j2,"\n" if $ascii>1;
           @puzzle[$k+$j2]=$l3;
           $neu++;
           return;
         }
       }
     }
   }
 }
}

sub senkrechtsquare() {
 my (@m,@m1,@m2,$j,$n,$n1,$n2,$j1,$j2,$j4,$l1,$l2,$l3);
 my ($k) = $_[0];
 my ($k1)=$k+27;
 my ($k2)=$k+54;
 if ($k/27>1) {$k1 = $k-27; $k2=$k+27}
 if ($k/27>2) {$k1 = $k-54; $k2 = $k-27}
 print "senkrechtsquare $k : $k1 $k2<br />\n" if $ascii>0;
 for ($j=1;$j<=9;$j++) {
   @m=('',0,0,0); @m1=('',0,0,0); @m2=(':',0,0,0);
   if (substr(@moeglich[$k],$j,1) eq $j) {@m[1]=$j}
   if (substr(@moeglich[$k+3],$j,1) eq $j) {@m[1]=$j}
   if (substr(@moeglich[$k+6],$j,1) eq $j) {@m[1]=$j}
   if (substr(@moeglich[$k+1],$j,1) eq $j) {@m[2]=$j}
   if (substr(@moeglich[$k+4],$j,1) eq $j) {@m[2]=$j}
   if (substr(@moeglich[$k+7],$j,1) eq $j) {@m[2]=$j}
   if (substr(@moeglich[$k+2],$j,1) eq $j) {@m[3]=$j}
   if (substr(@moeglich[$k+5],$j,1) eq $j) {@m[3]=$j}
   if (substr(@moeglich[$k+8],$j,1) eq $j) {@m[3]=$j}
   if (substr(@moeglich[$k1],$j,1) eq $j) {@m1[1]=$j}
   if (substr(@moeglich[$k1+3],$j,1) eq $j) {@m1[1]=$j}
   if (substr(@moeglich[$k1+6],$j,1) eq $j) {@m1[1]=$j}
   if (substr(@moeglich[$k1+1],$j,1) eq $j) {@m1[2]=$j}
   if (substr(@moeglich[$k1+4],$j,1) eq $j) {@m1[2]=$j}
   if (substr(@moeglich[$k1+7],$j,1) eq $j) {@m1[2]=$j}
   if (substr(@moeglich[$k1+2],$j,1) eq $j) {@m1[3]=$j}
   if (substr(@moeglich[$k1+5],$j,1) eq $j) {@m1[3]=$j}
   if (substr(@moeglich[$k1+8],$j,1) eq $j) {@m1[3]=$j}
   if (substr(@moeglich[$k2],$j,1) eq $j) {@m2[1]=$j}
   if (substr(@moeglich[$k2+3],$j,1) eq $j) {@m2[1]=$j}
   if (substr(@moeglich[$k2+6],$j,1) eq $j) {@m2[1]=$j}
   if (substr(@moeglich[$k2+1],$j,1) eq $j) {@m2[2]=$j}
   if (substr(@moeglich[$k2+4],$j,1) eq $j) {@m2[2]=$j}
   if (substr(@moeglich[$k2+7],$j,1) eq $j) {@m2[2]=$j}
   if (substr(@moeglich[$k2+2],$j,1) eq $j) {@m2[3]=$j}
   if (substr(@moeglich[$k2+5],$j,1) eq $j) {@m2[3]=$j}
   if (substr(@moeglich[$k2+8],$j,1) eq $j) {@m2[3]=$j}
   $n=0;
   $n++ if @m[1]==$j;
   $n++ if @m[2]==$j;
   $n++ if @m[3]==$j;
   $n1=0;
   if (@m1[1]==$j) { $n1++; $j1=1 }
   if (@m1[2]==$j) { $n1++; $j1=2 }
   if (@m1[3]==$j) { $n1++; $j1=3 }
   $n2=0;
   if (@m2[1]==$j) { $n2++; $j2=1 }
   if (@m2[2]==$j) { $n2++; $j2=2 }
   if (@m2[3]==$j) { $n2++; $j2=3 }
#   print "Suche nach $j: @m1 @m2 : $n1 $n2<br />\n";
   if (($n1==1 && $n2==1) && $n!=1) {
     if ($j1==1 || $j2==1) {
       substr(@moeglich[$k],$j,1)=' ';
       substr(@moeglich[$k+3],$j,1)=' ';
       substr(@moeglich[$k+6],$j,1)=' ';
     }
     if ($j1==2 || $j2==2) {
       substr(@moeglich[$k+1],$j,1)=' ';
       substr(@moeglich[$k+4],$j,1)=' ';
       substr(@moeglich[$k+7],$j,1)=' ';
     }
     if ($j1==3 || $j2==3) {
       substr(@moeglich[$k+2],$j,1)=' ';
       substr(@moeglich[$k+5],$j,1)=' ';
       substr(@moeglich[$k+8],$j,1)=' ';
     }
     $l3=0;
     for ($n=1; $n<=9; $n++) {
       if ($n!=$j) {
         $l1=0;
         $l2=0;
         for ($j1=0;$j1<=8;$j1++) {
           $l1++ if (substr(@moeglich[$k+$j1],$j,1)==$j && substr(@moeglich[$k+$j1],$n,1)==$n);
           $l2++ if (substr(@moeglich[$k+$j1],$j,1)!=$j && substr(@moeglich[$k+$j1],$n,1)==$n);
         }
         if ($l1==2 && $l2==0) {
           $l3++;
           $j2=$n;
         }
       }
     }
     if ($l3==1) {
#       print "n=$j2<br />\n";
       $l1=0;
       for ($j1=0;$j1<=8;$j1++) {
         if (substr(@moeglich[$k+$j1],$j,1)==$j &&
             substr(@moeglich[$k+$j1],$j2,1)==$j2) {
           if ($l1==0) {$l1=$j1} else {$l2=$j1}
         }
       }
#       print "l1=$l1 l2=$l2<br />\n";
       for ($j1=1;$j1<=9;$j1++) {
         if ($j1!=$j && $j1!=$j2) {
           substr(@moeglich[$k+$l1],$j1,1) =" ";
           substr(@moeglich[$k+$l2],$j1,1) =" ";
         }
       }
#       print "<pre>\n";
#       print "@moeglich[$k] : @moeglich[$k+1] : @moeglich[$k+2]\n"; 
#       print "@moeglich[$k+3] : @moeglich[$k+4] : @moeglich[$k+5]\n"; 
#       print "@moeglich[$k+6] : @moeglich[$k+7] : @moeglich[$k+8]\n"; 
#       print "@moeglich[$k1] : @moeglich[$k1+1] : @moeglich[$k1+2]\n"; 
#       print "@moeglich[$k1+3] : @moeglich[$k1+4] : @moeglich[$k1+5]\n"; 
#       print "@moeglich[$k1+6] : @moeglich[$k1+7] : @moeglich[$k1+8]\n"; 
#       print "@moeglich[$k2] : @moeglich[$k2+1] : @moeglich[$k2+2]\n"; 
#       print "@moeglich[$k2+3] : @moeglich[$k2+4] : @moeglich[$k2+5]\n"; 
#       print "@moeglich[$k2+6] : @moeglich[$k2+7] : @moeglich[$k2+8]\n"; 
#       print "</pre>\n";
       for ($j4=1;$j4<=9;$j4++) {
         $l1=0;
         for ($j2=0;$j2<=8;$j2++) {        
           if (substr(@moeglich[$k+$j2],$j4,1)==$j4) {$l1++; $l3=$j2}
         }
         if ($l1==1 && @puzzle[$k+$l3] eq "") {
           print "gefunden: $j4 an pos ",$k+$l3,"\n" if $ascii>1;
           @puzzle[$k+$l3]=$j4;
           $neu++;
           return;
         }
       }
     } else {
#       print "<pre>\n";
#       print "@moeglich[$k] : @moeglich[$k+1] : @moeglich[$k+2]\n"; 
#       print "@moeglich[$k+3] : @moeglich[$k+4] : @moeglich[$k+5]\n"; 
#       print "@moeglich[$k+6] : @moeglich[$k+7] : @moeglich[$k+8]\n"; 
#       print "@moeglich[$k1] : @moeglich[$k1+1] : @moeglich[$k1+2]\n"; 
#       print "@moeglich[$k1+3] : @moeglich[$k1+4] : @moeglich[$k1+5]\n"; 
#       print "@moeglich[$k1+6] : @moeglich[$k1+7] : @moeglich[$k1+8]\n"; 
#       print "@moeglich[$k2] : @moeglich[$k2+1] : @moeglich[$k2+2]\n"; 
#       print "@moeglich[$k2+3] : @moeglich[$k2+4] : @moeglich[$k2+5]\n"; 
#       print "@moeglich[$k2+6] : @moeglich[$k2+7] : @moeglich[$k2+8]\n"; 
#       print "</pre>\n";
       for ($j2=0;$j2<=8;$j2++) {        
         $l1=0;
         for ($j4=1;$j4<=9;$j4++) {
           if (substr(@moeglich[$k+$j2],$j4,1)==$j4) {$l1++; $l3=$j4}
         }
#         print "j2=$j2 l1=$l1 <br />\n";
         if ($l1==1 && @puzzle[$k+$j2] eq "") {
           print "gefunden: $l3 an pos ",$k+$j2,"\n" if $ascii>0;
           @puzzle[$k+$j2]=$l3;
           $neu++;
           return;
         }
       }
     }
   }
 }
}

sub printmoeglichkeiten() {
  my ($i);
  for ($i=0;$i<=55;$i=$i+27) {
    printpuzzle(1+$i); printpuzzle(2+$i); printpuzzle(3+$i);    print " ";
    printpuzzle(10+$i); printpuzzle(11+$i); printpuzzle(12+$i); print " ";
    printpuzzle(19+$i); printpuzzle(20+$i); printpuzzle(21+$i); print " ";
    print @moeglich[1+$i]."-".@moeglich[2+$i]."-".@moeglich[3+$i]." | ";
    print @moeglich[10+$i]."-".@moeglich[11+$i]."-".@moeglich[12+$i]." | ";
    print @moeglich[19+$i]."-".@moeglich[20+$i]."-".@moeglich[21+$i]."\n";
    printpuzzle(4+$i); printpuzzle(5+$i); printpuzzle(6+$i);    print " ";
    printpuzzle(13+$i); printpuzzle(14+$i); printpuzzle(15+$i); print " ";
    printpuzzle(22+$i); printpuzzle(23+$i); printpuzzle(24+$i); print " ";
    print @moeglich[4+$i]."-".@moeglich[5+$i]."-".@moeglich[6+$i]." | ";
    print @moeglich[13+$i]."-".@moeglich[14+$i]."-".@moeglich[15+$i]." | ";
    print @moeglich[22+$i]."-".@moeglich[23+$i]."-".@moeglich[24+$i]."\n";
    printpuzzle(7+$i); printpuzzle(8+$i); printpuzzle(9+$i);    print " ";
    printpuzzle(16+$i); printpuzzle(17+$i); printpuzzle(18+$i); print " ";
    printpuzzle(25+$i); printpuzzle(26+$i); printpuzzle(27+$i); print " ";
    print @moeglich[7+$i]."-".@moeglich[8+$i]."-".@moeglich[9+$i]." | ";
    print @moeglich[16+$i]."-".@moeglich[17+$i]."-".@moeglich[18+$i]." | ";
    print @moeglich[25+$i]."-".@moeglich[26+$i]."-".@moeglich[27+$i]."\n\n";
  }
}

sub digits() {
  my ($zahlen)='123456789';
  $fehler=0;
  for ($i=1;$i<=81;$i++) {
    if ($FORM{'p'.$i} ne "") {
       if (index($zahlen,$FORM{'p'.$i})<0) {
         $fehler=$i%9;
         $fehler=9 if $fehler==0;
         $fehler=$i-$fehler+1;
         @bgcolor[$fehler]="cc0000";
       }
    }
  }
}
  
sub proper() {
 my ($k) = $_[0];
 print "proper $k\n" if $ascii>1;
 my ($m,$l,$j,$n,$i,@pos,$p,$puz,$s,$t,$anf);
 $t=$k%9;
 $t=9 if $t==0;
 $t=$k-$t+1;
 $m=$k%27;
 $m=1 if ($m==4 || $m==7);
 $m=2 if ($m==5 || $m==8);
 $m=3 if ($m==6 || $m==9);
 $m=10 if ($m==13 || $m==16);
 $m=11 if ($m==14 || $m==17);
 $m=12 if ($m==15 || $m==18);
 $m=19 if ($m==22 || $m==25);
 $m=20 if ($m==23 || $m==26);
 $m=21 if ($m==24 || $m==0);
 $l=$k%9;
 $l=4 if ($l==5 || $l==6);
 $l=7 if ($l==8 || $l==0);
 $l=1 if $l<4;
 $l=$l+27 if $k>27;
 $l=$l+27 if $k>54;
 print "k=$k m=$m l=$l t=$t\n" if $ascii>1;
 @pos=($t,$t+1,$t+2,$t+3,$t+4,$t+5,$t+6,$t+7,$t+8,$m,$m+3,$m+6,$m+27,$m+30,$m+33,$m+54,$m+57,$m+60,$l,$l+1,$l+2,$l+9,$l+10,$l+11,$l+18,$l+19,$l+20);
 #print "                                         pos=@pos[3]\n" if $ascii>1;
 $n=0;
 for ($j=1; $j<=9; $j++) {
   print "suche nach $j\n" if $ascii==1;
   $anf=0;
   for ($p=0;$p<27;$p++) {
     $i=$j;
     $puz=@pos[$p];
     if ($puz!=$k) {
       $puz=@puzzle[$puz];
       print "testing :$puz:\n" if $ascii==1;
       if ($puz ne "") {
 #        print "testing :$puz:\n" if $p==3;
         if ($puz*1==$j) {
           $i=0;
           goto solit;
         }
       }
     }
   }
   solit:
   if ($i==$j) {
     $n++;
     $s=$j;
   }
 }
 if ($n==0) {
   $fehler=1;
   $j=$m%9;
   $i=9 if $j==0;
   $m=$m-$j+1;
   @bgcolor[$m]="cc0000";
   @bgcolor[$m+27]="cc0000";
   @bgcolor[$m+54]="cc0000";
   @bgcolor[$l]="cc0000";
   @bgcolor[$l+9]="cc0000";
   @bgcolor[$l+18]="cc0000";
 }
}

sub konsistenz() {
  $fehler=0;
  for ($i=1;$i<=73;$i=$i+9) {
   if (checkquadrat($i)>0) {
     @bgcolor[$i]="cc0000"; $fehler++;
   } else {
     @bgcolor[$i]="000099";
   }
  }
  
  if (checkcolumn(1)>0 || checkcolumn(2)>0 || checkcolumn(3)>0) {
    @bgcolor[1]="cc0000"; @bgcolor[28]="cc0000"; @bgcolor[55]="cc0000";
    $fehler++;
  }
  if (checkcolumn(10)>0 || checkcolumn(11)>0 || checkcolumn(12)>0) {
    @bgcolor[10]="cc0000"; @bgcolor[37]="cc0000"; @bgcolor[64]="cc0000";
    $fehler++;
  }
  if (checkcolumn(19)>0 || checkcolumn(20)>0 || checkcolumn(21)>0) {
    @bgcolor[19]="cc0000"; @bgcolor[46]="cc0000"; @bgcolor[73]="cc0000";
    $fehler++;
  }
  
  if (checkline(1)>0 || checkline(4)>0 || checkline(7)>0) {
    @bgcolor[1]="cc0000"; @bgcolor[10]="cc0000"; @bgcolor[19]="cc0000";
    $fehler++;
  }
  if (checkline(28)>0 || checkline(31)>0 || checkline(34)>0) {
    @bgcolor[28]="cc0000"; @bgcolor[37]="cc0000"; @bgcolor[46]="cc0000";
    $fehler++;
  }
  if (checkline(55)>0 || checkline(58)>0 || checkline(61)>0) {
    @bgcolor[55]="cc0000"; @bgcolor[64]="cc0000"; @bgcolor[73]="cc0000";
    $fehler++;
  }
}

sub tabout() {
 my ($i) = $_[0];
 print '<table border="0" bgcolor="#',@bgcolor[$i],'" cellspacing="2" cellpadding="1">';
 print '<tr bgcolor="#ffffff"><td bgcolor="#',@hinter[$i],'" align="center" width="29" height="26">';
 if ($FORM{'p'.$i} eq "") {
   print '<input type="text" maxlength="1" ';
   print 'size="1" name="p',$i.$unique,'" value="',@puzzle[$i],'" />';
   $neuzahl=$neuzahl.@puzzle[$i];
 } else {
   if ($fehler==0) {
     print "<b>$FORM{'p'.$i}</b>\n";
     print '<input type="hidden" ';
   } else {
     print '<input type="text" maxlength="1" size="1" ';
   }
   print 'name="p',$i.$unique,'" value="',$FORM{'p'.$i},'" />';
 }
 $i++;
 print '</td><td bgcolor="#',@hinter[$i],'" align="center" width="29" height="26">';
 if ($FORM{'p'.$i} eq "") {
   print '<input type="text" maxlength="1" ';
   print 'size="1" name="p',$i.$unique,'" value="',@puzzle[$i],'" />';
   $neuzahl=$neuzahl.@puzzle[$i];
 } else {
   if ($fehler==0) {
     print "<b>$FORM{'p'.$i}</b>\n";
     print '<input type="hidden" ';
   } else {
     print '<input type="text" maxlength="1" size="1" ';
   }
   print 'name="p',$i.$unique,'" value="',$FORM{'p'.$i},'" />';
 }
 $i++;
 print '</td><td bgcolor="#',@hinter[$i],'" align="center" width="29" height="26">';
 if ($FORM{'p'.$i} eq "") {
   print '<input type="text" maxlength="1" ';
   print 'size="1" name="p',$i.$unique,'" value="',@puzzle[$i],'" />';
   $neuzahl=$neuzahl.@puzzle[$i];
 } else {
   if ($fehler==0) {
     print "<b>$FORM{'p'.$i}</b>\n";
     print '<input type="hidden" ';
   } else {
     print '<input type="text" maxlength="1" size="1" ';
   }
   print 'name="p',$i.$unique,'" value="',$FORM{'p'.$i},'" />';
 }
 $i++;
 print "</td></tr>\n";
 print '<tr bgcolor="#ffffff"><td bgcolor="#',@hinter[$i],'" align="center" width="29" height="26">';
 if ($FORM{'p'.$i} eq "") {
   print '<input type="text" maxlength="1" ';
   print 'size="1" name="p',$i.$unique,'" value="',@puzzle[$i],'" />';
   $neuzahl=$neuzahl.@puzzle[$i];
 } else {
   if ($fehler==0) {
     print "<b>$FORM{'p'.$i}</b>\n";
     print '<input type="hidden" ';
   } else {
     print '<input type="text" maxlength="1" size="1" ';
   }
   print 'name="p',$i.$unique,'" value="',$FORM{'p'.$i},'" />';
 }
 $i++;
 print '</td><td bgcolor="#',@hinter[$i],'" align="center" width="29" height="26">';
 if ($FORM{'p'.$i} eq "") {
   print '<input type="text" maxlength="1" ';
   print 'size="1" name="p',$i.$unique,'" value="',@puzzle[$i],'" />';
   $neuzahl=$neuzahl.@puzzle[$i];
 } else {
   if ($fehler==0) {
     print "<b>$FORM{'p'.$i}</b>\n";
     print '<input type="hidden" ';
   } else {
     print '<input type="text" maxlength="1" size="1" ';
   }
   print 'name="p',$i.$unique,'" value="',$FORM{'p'.$i},'" />';
 }
 $i++;
 print '</td><td bgcolor="#',@hinter[$i],'" align="center" width="29" height="26">';
 if ($FORM{'p'.$i} eq "") {
   print '<input type="text" maxlength="1" ';
   print 'size="1" name="p',$i.$unique,'" value="',@puzzle[$i],'" />';
   $neuzahl=$neuzahl.@puzzle[$i];
 } else {
   if ($fehler==0) {
     print "<b>$FORM{'p'.$i}</b>\n";
     print '<input type="hidden" ';
   } else {
     print '<input type="text" maxlength="1" size="1" ';
   }
   print 'name="p',$i.$unique,'" value="',$FORM{'p'.$i},'" />';
 }
 $i++;
 print "</td></tr>\n";
 print '<tr bgcolor="#ffffff"><td bgcolor="#',@hinter[$i],'" align="center" width="29" height="26">';
 if ($FORM{'p'.$i} eq "") {
   print '<input type="text" maxlength="1" ';
   print 'size="1" name="p',$i.$unique,'" value="',@puzzle[$i],'" />';
   $neuzahl=$neuzahl.@puzzle[$i];
 } else {
   if ($fehler==0) {
     print "<b>$FORM{'p'.$i}</b>\n";
     print '<input type="hidden" ';
   } else {
     print '<input type="text" maxlength="1" size="1" ';
   }
   print 'name="p',$i.$unique,'" value="',$FORM{'p'.$i},'" />';
 }
 $i++;
 print '</td><td bgcolor="#',@hinter[$i],'" align="center" width="29" height="26">';
 if ($FORM{'p'.$i} eq "") {
   print '<input type="text" maxlength="1" ';
   print 'size="1" name="p',$i.$unique,'" value="',@puzzle[$i],'" />';
   $neuzahl=$neuzahl.@puzzle[$i];
 } else {
   if ($fehler==0) {
     print "<b>$FORM{'p'.$i}</b>\n";
     print '<input type="hidden" ';
   } else {
     print '<input type="text" maxlength="1" size="1" ';
   }
   print 'name="p',$i.$unique,'" value="',$FORM{'p'.$i},'" />';
 }
 $i++;
 print '</td><td bgcolor="#',@hinter[$i],'" align="center" width="29" height="26">';
 if ($FORM{'p'.$i} eq "") {
   print '<input type="text" maxlength="1" ';
   print 'size="1" name="p',$i.$unique,'" value="',@puzzle[$i],'" />';
   $neuzahl=$neuzahl.@puzzle[$i];
 } else {
   if ($fehler==0) {
     print "<b>$FORM{'p'.$i}</b>\n";
     print '<input type="hidden" ';
   } else {
     print '<input type="text" maxlength="1" size="1" ';
   }
   print 'name="p',$i.$unique,'" value="',$FORM{'p'.$i},'" />';
 }
 $i++;
 print "</td></tr>\n";
 print "</table>\n";
}

sub checkquadrat() {
 my ($i) = $_[0];
 my (@anzahl)=(0,0,0,0,0,0,0,0,0,0);
 my ($j,$k);
 for ($j=$i; $j<$i+9; $j++) {
   $k=@puzzle[$j]*1;
#   print "j=$j  k=$k\n";
   @anzahl[$k]++;
   if (@anzahl[$k]>1 && $k!=0) {return 1}
 }
 return 0;
}

sub checkcolumn() {
 my ($i) = $_[0];
 my (@anzahl)=(0,0,0,0,0,0,0,0,0,0);
 my ($k,$j);
 for ($j=1;$j<=3;$j++) {
  $k=@puzzle[$i]*1;
  @anzahl[$k]++;
  if (@anzahl[$k]>1 && $k!=0) {return 1};
  $i=$i+3;
  $k=@puzzle[$i]*1;
  @anzahl[$k]++;
  if (@anzahl[$k]>1 && $k!=0) {return 1};
  $i=$i+3;
  $k=@puzzle[$i]*1;
  @anzahl[$k]++;
  if (@anzahl[$k]>1 && $k!=0) {return 1};
  $i=$i+21;
 }
 return 0;
}

sub checkline() {
 my ($i) = $_[0];
 my (@anzahl)=(0,0,0,0,0,0,0,0,0,0);
 my ($k,$j);
 for ($j=1;$j<=3;$j++) {
  $k=@puzzle[$i]*1;
  @anzahl[$k]++;
  if (@anzahl[$k]>1 && $k!=0) {return 1};
  $i++;
  $k=@puzzle[$i]*1;
  @anzahl[$k]++;
  if (@anzahl[$k]>1 && $k!=0) {return 1};
  $i++;
  $k=@puzzle[$i]*1;
  @anzahl[$k]++;
  if (@anzahl[$k]>1 && $k!=0) {return 1};
  $i=$i+7;
 }
 return 0;
}

sub printpuzzle() {
  my ($k)=$_[0];
  if (@puzzle[$k] eq "") {print "."} else {print @puzzle[$k]}
}

sub testcol() {
  my ($k)=$_[0];
  my ($j)=$_[1];
  my ($n1)=0;
  $n1++ if substr(@moeglich[$k],$j,1) eq $j;
  $n1++ if substr(@moeglich[$k+3],$j,1) eq $j;
  $n1++ if substr(@moeglich[$k+6],$j,1) eq $j;
  my ($n2)=0;
  $n2++ if substr(@moeglich[$k+1],$j,1) eq $j;
  $n2++ if substr(@moeglich[$k+4],$j,1) eq $j;
  $n2++ if substr(@moeglich[$k+7],$j,1) eq $j;
  my ($n3)=0;
  $n3++ if substr(@moeglich[$k+2],$j,1) eq $j;
  $n3++ if substr(@moeglich[$k+5],$j,1) eq $j;
  $n3++ if substr(@moeglich[$k+8],$j,1) eq $j;
#  print "testcol $k for $j : $n1 $n2 $n3\n" if $ascii>1;
  return 0 if $n1+$n2+$n3==1;
  return 1 if ($n2+$n3==0 && $n1>0);
  return 2 if ($n1+$n3==0 && $n2>0);
  return 3 if ($n1+$n2==0 && $n3>0);
  return 0;
}     

sub testrow() {
  my ($k)=$_[0];
  my ($j)=$_[1];
  my ($n1)=0;
  $n1++ if substr(@moeglich[$k],$j,1) eq $j;
  $n1++ if substr(@moeglich[$k+1],$j,1) eq $j;
  $n1++ if substr(@moeglich[$k+2],$j,1) eq $j;
  my ($n2)=0;
  $n2++ if substr(@moeglich[$k+3],$j,1) eq $j;
  $n2++ if substr(@moeglich[$k+4],$j,1) eq $j;
  $n2++ if substr(@moeglich[$k+5],$j,1) eq $j;
  my ($n3)=0;
  $n3++ if substr(@moeglich[$k+6],$j,1) eq $j;
  $n3++ if substr(@moeglich[$k+7],$j,1) eq $j;
  $n3++ if substr(@moeglich[$k+8],$j,1) eq $j;
#  print "testrow $k for $j : $n1 $n2 $n3\n" if $ascii>1;
  return 0 if $n1+$n2+$n3==1;
  return 1 if ($n2+$n3==0 && $n1>0);
  return 2 if ($n1+$n3==0 && $n2>0);
  return 3 if ($n1+$n2==0 && $n3>0);
  return 0;
}     

sub paarcol() {
  my ($i)=$_[0];
  print "paarcol $i\n" if $ascii>0;
  @paarzahl=@moeglich;
  paare(0,$i,$i+3,$i+6,$i+27,$i+30,$i+33,$i+54,$i+57,$i+60);
}

sub paarrow() {
  my ($i)=$_[0];
  print "paarrow $i\n" if $ascii>0;
  @paarzahl=@moeglich;
  paare(0,$i,$i+1,$i+2,$i+9,$i+10,$i+11,$i+18,$i+19,$i+20);
}

sub paarsqu() {
  my ($i)=$_[0];
  print "paarsqu $i\n" if $ascii>0;
  @paarzahl=@moeglich;
  paare(0,$i,$i+1,$i+2,$i+3,$i+4,$i+5,$i+6,$i+7,$i+8);
}

sub oldpaare() {
  my ($j,$k,$paar1,$paar2,@col,$p1,$p2,$s);
  for ($j=1;$j<=8;$j++) {
    $paar1=@moeglich[@_[$j]];
    $paar1=~s- --g;
    if ($paar1>9 && $paar1<=89) {
#      print "i=$i j=$j paar=$paar1\n" if $ascii>0;
      for ($k=$j+1;$k<=9;$k++) {
        $paar2=@moeglich[@_[$k]];
        $paar2=~s- --g;
        if ($paar1==$paar2) {
          $p1=$paar1%10;
          $p2=int($paar1/10);
          $merkzahl=$p2.' und '.$p1;
          print "i=$i @_[$j] @_[$k] $p1 $p2\n" if $ascii>0;
          for ($i=1;$i<=9;$i++) {
            $s=@_[$i];
            if ($s!=@_[$j] && $s!=@_[$k]) {
              substr(@moeglich[$s],$p1,1)=' ';
              substr(@moeglich[$s],$p2,1)=' ';
            }
          }
        }
      }
    }
  }
nochmals:
  for ($j=1;$j<=9;$j++) {
    $s=@_[$j];
    $p1=@moeglich[$s];
    $p1 =~ s- --g;
    if ($p1>0 && $p1<=9 && @puzzle[$s] eq "") {
      defpuzzle($s,$p1);
      $paarz=$s;
      $neu++;
      return if $FORM{'level'} eq "stepwize";
      goto nochmals;
    }
  }
  
}

sub paare() {
  my ($j,$k,$paar1,$paar2,@col,$p1,$p2,$s,$paar3,$m,$paar4);
  for ($p1=1; $p1<=8; $p1++) {
    for ($p2=$p1+1; $p2<=9; $p2++) {
      $mehrzahl=$p1*10+$p2;
#      print "mehrzahl=$mehrzahl\n";
      $k=0;
      $s=0;
      $paar2=0;
      $m=0;
      $paar4=0;
      for ($j=1;$j<=9;$j++) {
        $paar1=@moeglich[@_[$j]];
        print "$p1 $p2 $paar1 \n" if $ascii>0;
        if (substr($paar1,$p1,1) eq ' ' && substr($paar1,$p2,1) eq ' ') {
          $k++;
        } else {
          if (substr($paar1,$p1,1)==$p1 && substr($paar1,$p2,1)==$p2) {
            $paar3=$paar1;
            substr($paar3,$p1,1)=' ';
            substr($paar3,$p2,1)=' ';
            $paar3 =~ s/ //g;
            if ($paar3 eq '') {
              $m++;
              $paar4=$paar4*10+$j;
            }  
            $s++;
            $paar2=$paar2*10+$j;
          }
        }
      }
      print "$p1 $p2 s=$s k=$k $paar2 m=$m $paar4\n" if $ascii>0;
      if ($m==2) {
        $s=2;
        $k=7;
        $paar2=$paar4;
      }
      if ($s==2 && $k==7) {
        $paar1=$paar2%10;
        $paar2=int(($paar2-$paar1)/10);
        $paar1=@_[$paar1];
        $paar2=@_[$paar2];
        for ($j=1;$j<=9;$j++) {
          $s=@_[$j];
          if ($s==$paar1 || $s==$paar2) {
            @moeglich[$s]=' 'x10;
            substr(@moeglich[$s],$p1,1)=$p1;
            substr(@moeglich[$s],$p2,1)=$p2;
          } else {
            substr(@moeglich[$s],$p1,1)=' ';
            substr(@moeglich[$s],$p2,1)=' ';
          }
        }
        printmoeglichkeiten() if $ascii>0;
        for ($k=1;$k<=9;$k++) {
          $reason=16;
          einzigrow(1,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigrow(4,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigrow(7,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigrow(28,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigrow(31,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigrow(34,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigrow(55,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigrow(58,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigrow(61,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          $reason=17;
          einzigcol(1,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigcol(2,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigcol(3,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigcol(10,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigcol(11,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigcol(12,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigcol(19,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigcol(20,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigcol(21,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          $reason=18;
          einzigsqu(1,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigsqu(10,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigsqu(19,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigsqu(28,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigsqu(37,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigsqu(46,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigsqu(55,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigsqu(64,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
          einzigsqu(73,$k); goto skip if($neu>0 && $FORM{'level'} eq 'stepwize');
        }
      }
    }
  }
}

sub einzigrow() {
  my ($k)=$_[0];
  my ($j)=$_[1];
  einzig($j,$k,$k+1,$k+2,$k+9,$k+10,$k+11,$k+18,$k+19,$k+20);
}     

sub einzigcol() {
  my ($k)=$_[0];
  my ($j)=$_[1];
  einzig($j,$k,$k+3,$k+6,$k+27,$k+30,$k+33,$k+54,$k+57,$k+60);
}     

sub einzigsqu() {
  my ($k)=$_[0];
  my ($j)=$_[1];
  einzig($j,$k,$k+1,$k+2,$k+3,$k+4,$k+5,$k+6,$k+7,$k+8);
}     

sub einzig() {
  my ($l);
  my ($n)=0;
  my ($i);
  print "einzig: $_[0] " if $ascii>1;
  for ($l=1;$l<=9;$l++) {
    print "$_[$l] " if $ascii>1;
    if (substr(@moeglich[$_[$l]],$_[0],1) eq $_[0]) { $n++; $i=$_[$l]; }
  }
  print "n=$n i=$i\n" if $ascii>1;
  if ($n==1) {
    if (@puzzle[$i] eq "") {
      defpuzzle($i,$_[0]);
      $neu++;
      return if $FORM{'level'} eq 'stepwize';
    }
  }
  for ($l=1;$l<=9;$l++) {
    print "$_[$l] " if $ascii>1;
    $i=@moeglich[$_[$l]];
    $i =~ s- --g;
    if ($i<=9 && $i>0) {
      $n=$_[$l]; 
      if (@puzzle[$n] eq "") {
        defpuzzle($n,$i);
        $neu++;
        $reason=19;
        return if $FORM{'level'} eq 'stepwize';
      }
    }
  }
}     

sub doppelrowtest() {
  my ($j)=$_[0];
  my ($k)=$_[1];
  my (@z)=(0,0,0,0);
  my ($l,$m);
  my ($n)=0;
#  print "doppelrowtest: square ($k) $j may be present in these 2 rows: " if $ascii>0;
  for ($l=0;$l<9;$l++) {
    $m=int($l/3)+1;
    @z[$m]++ if substr(@moeglich[$k+$l],$j,1) eq $j;
  }
  $n++ if @z[1]>0;
  $n++ if @z[2]>0;
  $n++ if @z[3]>0;
  $k=0;
  if ($n==2) {
    if (@z[1]>0) {$k=1}
    if (@z[2]>0) {$k=10*$k+2}
    if (@z[3]>0) {$k=10*$k+3}
  }
#  print "$k\n" if ($ascii>0);
  return $k;
}

sub doppelcoltest() {
  my ($j)=$_[0];
  my ($k)=$_[1];
  my (@z)=(0,0,0,0);
  my ($l,$m);
  my ($n)=0;
#  print "doppelcoltest: square ($k) $j may be present in these 2 cols: " if $ascii>0;
  for ($l=0;$l<9;$l++) {
    $m=$l%3+1;
    @z[$m]++ if substr(@moeglich[$k+$l],$j,1) eq $j;
  }
  $n++ if @z[1]>0;
  $n++ if @z[2]>0;
  $n++ if @z[3]>0;
  $k=0;
  if ($n==2) {
    if (@z[1]>0) {$k=1}
    if (@z[2]>0) {$k=10*$k+2}
    if (@z[3]>0) {$k=10*$k+3}
  }
#  print "$k\n" if ($ascii>0);
  return $k;
}

sub dualcol() {
  my ($j,$n,$z,$x);
  my ($l)=' 'x10;
  my ($r)=' 'x10;
  for ($j=1;$j<=9;$j++) {
    my ($k)=0;
    for ($z=0;$z<9;$z++) {
      $k++ if substr(@moeglich[@_[$z]],$j,1) eq $j;
    }
    substr($l,$j,1)=$k;
  }
  for ($j=1;$j<=9;$j++) {
   if (substr($l,$j,1)==2) {
    for ($n=$j+1;$n<=9;$n++) {
     $k=0;
     if (substr($l,$n,1)==2) {
       for ($z=0;$z<9;$z++) {
         $k++ if (substr(@moeglich[@_[$z]],$j,1) eq $j &&
                  substr(@moeglich[@_[$z]],$n,1) eq $n);
       }
       if ($k==2) {
         for ($z=0;$z<9;$z++) {
           if (substr(@moeglich[@_[$z]],$j,1) eq $j &&
               substr(@moeglich[@_[$z]],$n,1) eq $n) {
             $x=@moeglich[@_[$z]];
             @moeglich[@_[$z]]=' 'x10;
             substr(@moeglich[@_[$z]],$j,1)=$j;
             substr(@moeglich[@_[$z]],$n,1)=$n;
             if ($x ne @moeglich[@_[$z]]) {
               substr($r,$j,1)=2;
               substr($r,$n,1)=2;
             }
           }
         }
       }
     }
    }
   }
  }
  return $r;
}

sub tripelcol() {
  my ($l)=' 'x10;
  my ($i,$j1,$j2,$j3,@mgl,$n);
  for ($j1=1;$j1<=7;$j1++) {
    for ($j2=$j1+1;$j2<=8;$j2++) {
      for ($j3=$j2+1;$j3<=9;$j3++) {
        $n=0;
        for ($i=0;$i<=8;$i++) {
          @mgl[$i]=@moeglich[@_[$i]];
          substr(@mgl[$i],$j1,1)=' ';
          substr(@mgl[$i],$j2,1)=' ';
          substr(@mgl[$i],$j3,1)=' ';
          @mgl[$i] =~ s/ //g;
          $n++ if @mgl[$i] eq '';
        }
        if ($n==3) {
          substr($l,$j1,1)=$j1;
          substr($l,$j2,1)=$j2;
          substr($l,$j3,1)=$j3;
        }
      }
    }
  }
  $i=$l;
  $i =~ s / //g;
  $l=' 'x10 if ($i<100 || $i>999);
  if ($l ne '          ') {
    $i=$l;
    $i =~ s/ //g;
    $j1=$i%10;
    $i=($i-$j1)/10;
    $j2=$i%10;
    $j3=int($i/10);
    for ($i=0;$i<=8;$i++) {
      @mgl[$i]=@moeglich[@_[$i]];
      substr(@mgl[$i],$j1,1)=' ';
      substr(@mgl[$i],$j2,1)=' ';
      substr(@mgl[$i],$j3,1)=' ';
    }
    for ($i=0;$i<=8;$i++) {
      if (@mgl[$i] ne '          ') {
        substr(@moeglich[@_[$i]],$j1,1)=' ';
        substr(@moeglich[@_[$i]],$j2,1)=' ';
        substr(@moeglich[@_[$i]],$j3,1)=' ';
      }
    }
    for ($i=0;$i<=8;$i++) {
      if (@puzzle[@_[$i]] eq '') {
        $j1=@moeglich[@_[$i]];
        $j1 =~ s/ //g;
        if ($j1>0 && $j1<=9) {
          defpuzzle(@_[$i],$j1);
          $neu++;
        }
      }
    }
  }
  return $l;
}

sub defpuzzle() {
  my ($i)=$_[0];
  my ($j)=$_[1];
  my ($k,$m);
  print "gefunden: $j auf pos $i\n" if $ascii>0;
        @puzzle[$i]=$j;
        $k=$i%27;
        $k=27 if $k==0;
        $k=1 if ($k==4 || $k==7);
        $k=2 if ($k==5 || $k==8);
        $k=3 if ($k==6 || $k==9);
        $k=10 if ($k==13 || $k==16);
        $k=11 if ($k==14 || $k==17);
        $k=12 if ($k==15 || $k==18);
        $k=19 if ($k==22 || $k==25);
        $k=20 if ($k==23 || $k==26);
        $k=21 if ($k==24 || $k==27);
        substr(@moeglich[$k],$j,1)=' ';
        substr(@moeglich[$k+3],$j,1)=' ';
        substr(@moeglich[$k+6],$j,1)=' ';
        substr(@moeglich[$k+27],$j,1)=' ';
        substr(@moeglich[$k+30],$j,1)=' ';
        substr(@moeglich[$k+33],$j,1)=' ';
        substr(@moeglich[$k+54],$j,1)=' ';
        substr(@moeglich[$k+57],$j,1)=' ';
        substr(@moeglich[$k+60],$j,1)=' ';
        $m=$i-$k+1;
        substr(@moeglich[$m],$j,1)=' ';
        substr(@moeglich[$m+1],$j,1)=' ';
        substr(@moeglich[$m+2],$j,1)=' ';
        substr(@moeglich[$m+9],$j,1)=' ';
        substr(@moeglich[$m+10],$j,1)=' ';
        substr(@moeglich[$m+11],$j,1)=' ';
        substr(@moeglich[$m+18],$j,1)=' ';
        substr(@moeglich[$m+19],$j,1)=' ';
        substr(@moeglich[$m+20],$j,1)=' ';
        if ($i<=9) {$m=1}
        elsif ($i<=18) {$m=10}
        elsif ($i<=27) {$m=19}
        elsif ($i<=36) {$m=28}
        elsif ($i<=45) {$m=37}
        elsif ($i<=54) {$m=46}
        elsif ($i<=63) {$m=55}
        elsif ($i<=72) {$m=64}
        else {$m=73}
        substr(@moeglich[$m],$j,1)=' ';
        substr(@moeglich[$m+1],$j,1)=' ';
        substr(@moeglich[$m+2],$j,1)=' ';
        substr(@moeglich[$m+3],$j,1)=' ';
        substr(@moeglich[$m+4],$j,1)=' ';
        substr(@moeglich[$m+5],$j,1)=' ';
        substr(@moeglich[$m+6],$j,1)=' ';
        substr(@moeglich[$m+7],$j,1)=' ';
        substr(@moeglich[$m+8],$j,1)=' ';
        @moeglich[$i]=" "x10;
        substr(@moeglich[$i],$j,1)=$j;
}
