' Generates SelfOrthogonal Latin Diagonal Squares (9 x 9)
' Compact (3 x 3), Third-rows and Third-columns Summing to s1/3
' Tested with Office 365 under Windows 11
Sub SudSqr9e()
Dim a(81), b(9)
Dim b2(81), c2(81), a0(9, 9)
y = MsgBox("Locked", vbCritical, "Routine SudSqr9e")
End
n2 = 0: n9 = 0: k1 = 1: k2 = 1
m1 = 0: m2 = 8: s1 = 36
Sheets("Klad1").Select
t1 = Timer
' Row 1
For j81 = m1 To m2 'a(81)
a(81) = j81
For j80 = m1 To m2 'a(80)
a(80) = j80
If a(80) = a(81) Then GoTo 800
a(79) = s1 / 3 - a(80) - a(81)
If a(79) < m1 Or a(79) > m2 Then GoTo 800
If a(79) = a(80) Or a(79) = a(81) Then GoTo 800
For j78 = m1 To m2 'a(78)
a(78) = j78
If a(78) = a(79) Or a(78) = a(80) Or a(78) = a(81) Then GoTo 780
For j77 = m1 To m2 'a(77)
a(77) = j77
If a(77) = a(78) Or a(77) = a(79) Or a(77) = a(80) Or a(77) = a(81) Then GoTo 770
a(76) = s1 / 3 - a(77) - a(78)
If a(76) < m1 Or a(76) > m2 Then GoTo 770
If a(76) = a(77) Or a(76) = a(78) Or a(76) = a(79) Or a(76) = a(80) Or a(76) = a(81) Then GoTo 770
For j75 = m1 To m2 'a(75)
a(75) = j75
If a(75) = a(77) Or a(75) = a(78) Or a(75) = a(79) Or a(75) = a(80) Or a(75) = a(81) Then GoTo 750
If a(75) = a(76) Then GoTo 750
For j74 = m1 To m2 'a(74)
a(74) = j74
If a(74) = a(77) Or a(74) = a(78) Or a(74) = a(79) Or a(74) = a(80) Or a(74) = a(81) Then GoTo 740
If a(74) = a(75) Or a(74) = a(76) Then GoTo 740
a(73) = s1 / 3 - a(74) - a(75)
If a(73) < m1 Or a(73) > m2 Then GoTo 740
If a(73) = a(77) Or a(73) = a(78) Or a(73) = a(79) Or a(73) = a(80) Or a(73) = a(81) Then GoTo 740
If a(73) = a(74) Or a(73) = a(75) Or a(73) = a(76) Then GoTo 740
' Row 2
For j72 = m1 To m2 'a(72)
a(72) = j72
If a(72) = a(81) Then GoTo 720
If a(72) = a(80) Then GoTo 720
For j71 = m1 To m2 'a(71)
a(71) = j71
If a(71) = a(80) Then GoTo 710
If a(71) = a(72) Then GoTo 710
If a(71) = a(81) Then GoTo 710 'Diagonal
a(70) = s1 / 3 - a(71) - a(72)
If a(70) < m1 Or a(70) > m2 Then GoTo 710
If a(70) = a(71) Or a(70) = a(72) Then GoTo 710
For j69 = m1 To m2 'a(69)
a(69) = j69
If a(69) = a(78) Then GoTo 690
If a(69) = a(70) Or a(69) = a(71) Or a(69) = a(72) Then GoTo 690
For j68 = m1 To m2 'a(68)
a(68) = j68
If a(68) = a(77) Then GoTo 680
If a(68) = a(69) Or a(68) = a(70) Or a(68) = a(71) Or a(68) = a(72) Then GoTo 680
a(67) = s1 / 3 - a(68) - a(69)
If a(67) < m1 Or a(67) > m2 Then GoTo 680
If a(67) = a(68) Or a(67) = a(69) Or a(67) = a(70) Or a(67) = a(71) Or a(67) = a(72) Then GoTo 680
For j66 = m1 To m2 'a(66)
a(66) = j66
If a(66) = a(75) Then GoTo 660
If a(66) = a(68) Or a(66) = a(69) Or a(66) = a(70) Or a(66) = a(71) Or a(66) = a(72) Then GoTo 660
If a(66) = a(67) Then GoTo 660
For j65 = m1 To m2 'a(65)
a(65) = j65
If a(65) = a(74) Then GoTo 650
If a(65) = a(68) Or a(65) = a(69) Or a(65) = a(70) Or a(65) = a(71) Or a(65) = a(72) Then GoTo 650
If a(65) = a(66) Or a(65) = a(67) Then GoTo 650
If a(65) = a(73) Then GoTo 650 'Diagonal
a(64) = s1 / 3 - a(65) - a(66)
If a(64) < m1 Or a(64) > m2 Then GoTo 650
If a(64) = a(68) Or a(64) = a(69) Or a(64) = a(70) Or a(64) = a(71) Or a(64) = a(72) Then GoTo 650
If a(64) = a(65) Or a(64) = a(66) Or a(64) = a(67) Then GoTo 650
If a(64) = a(73) Then GoTo 650
' Row 3
a(63) = s1 / 3 - a(72) - a(81)
If a(63) < m1 Or a(63) > m2 Then GoTo 650
If a(63) = a(79) Then GoTo 650
a(62) = s1 / 3 - a(71) - a(80)
If a(62) < m1 Or a(62) > m2 Then GoTo 650
If a(62) = a(70) Then GoTo 650
a(61) = -s1 / 3 + a(71) + a(72) + a(80) + a(81)
If a(61) < m1 Or a(61) > m2 Then GoTo 650
If a(61) = a(71) Or a(61) = a(81) Then GoTo 650 'Diagonal
a(60) = s1 / 3 - a(69) - a(78)
If a(60) < m1 Or a(60) > m2 Then GoTo 650
a(59) = s1 / 3 - a(68) - a(77)
If a(59) < m1 Or a(59) > m2 Then GoTo 650
a(58) = -s1 / 3 + a(68) + a(69) + a(77) + a(78)
If a(59) < m1 Or a(59) > m2 Then GoTo 650
a(57) = s1 / 3 - a(66) - a(75)
If a(57) < m1 Or a(57) > m2 Then GoTo 650
a(56) = s1 / 3 - a(65) - a(74)
If a(56) < m1 Or a(56) > m2 Then GoTo 650
a(55) = -s1 / 3 + a(65) + a(66) + a(74) + a(75)
If a(55) < m1 Or a(55) > m2 Then GoTo 650
For i1 = 1 To 9 'Check Row 3
b(i1) = a(i1 + 54)
Next i1
GoSub 1860: If fl1 = 0 Then GoTo 650
For i1 = 55 To 63 'Check Columns
If a(i1) = a(i1 + 9) Then GoTo 650
If a(i1) = a(i1 + 18) Then GoTo 650
Next i1
' Row 4
For j54 = m1 To m2 'a(54)
a(54) = j54
If a(54) = a(63) Or a(54) = a(72) Or a(54) = a(81) Then GoTo 540
If a(54) = a(78) Then GoTo 540
For j53 = m1 To m2 'a(53)
a(53) = j53
If a(53) = a(54) Then GoTo 530
If a(53) = a(62) Or a(53) = a(71) Or a(53) = a(80) Then GoTo 530
If a(53) = a(69) Then GoTo 530
a(52) = s1 / 3 - a(53) - a(54)
If a(52) < m1 Or a(52) > m2 Then GoTo 530
a(51) = a(54) + a(78) - a(81)
If a(51) < m1 Or a(51) > m2 Then GoTo 530
If a(51) = a(61) Or a(51) = a(71) Or a(51) = a(81) Then GoTo 530 'Check Diagonal
a(50) = a(53) + a(77) - a(80)
If a(50) < m1 Or a(50) > m2 Then GoTo 530
a(49) = s1 / 3 - a(50) - a(51)
If a(49) < m1 Or a(49) > m2 Then GoTo 530
If a(49) = a(57) Or a(49) = a(65) Or a(49) = a(73) Then GoTo 530 'Check Diagonal
a(48) = a(54) + a(75) - a(81)
If a(48) < m1 Or a(48) > m2 Then GoTo 530
a(47) = a(53) + a(74) - a(80)
If a(47) < m1 Or a(47) > m2 Then GoTo 530
a(46) = s1 / 3 - a(47) - a(48)
If a(46) < m1 Or a(46) > m2 Then GoTo 530
For i1 = 1 To 9 'Check Row 4
b(i1) = a(i1 + 45)
Next i1
GoSub 1860: If fl1 = 0 Then GoTo 530
For i1 = 46 To 54 'Check Columns
If a(i1) = a(i1 + 9) Then GoTo 530
If a(i1) = a(i1 + 18) Then GoTo 530
If a(i1) = a(i1 + 27) Then GoTo 530
Next i1
' Row 5
For j45 = m1 To m2 'a(45)
a(45) = j45
If a(45) = a(54) Or a(45) = a(63) Or a(45) = a(72) Or a(45) = a(81) Then GoTo 450
If a(45) = a(77) Then GoTo 450
For j44 = m1 To m2 'a(44)
a(44) = j44
If a(44) = a(45) Then GoTo 440
If a(44) = a(53) Or a(44) = a(62) Or a(44) = a(71) Or a(44) = a(80) Then GoTo 440
If a(44) = a(68) Then GoTo 440
a(43) = s1 / 3 - a(44) - a(45)
If a(43) < m1 Or a(43) > m2 Then GoTo 440
a(42) = a(45) + a(69) - a(72)
If a(42) < m1 Or a(42) > m2 Then GoTo 440
a(41) = a(44) + a(68) - a(71)
If a(41) < m1 Or a(41) > m2 Then GoTo 440
If a(41) = a(51) Or a(41) = a(61) Or a(41) = a(71) Or a(41) = a(81) Then GoTo 440 'Check Diagonal
If a(41) = a(49) Or a(41) = a(57) Or a(41) = a(65) Or a(41) = a(73) Then GoTo 440 'Check Diagonal
a(40) = s1 / 3 - a(41) - a(42)
If a(40) < m1 Or a(40) > m2 Then GoTo 440
a(39) = a(45) + a(66) - a(72)
If a(39) < m1 Or a(39) > m2 Then GoTo 440
a(38) = a(44) + a(65) - a(71)
If a(38) < m1 Or a(38) > m2 Then GoTo 440
a(37) = s1 / 3 - a(38) - a(39)
If a(37) < m1 Or a(37) > m2 Then GoTo 440
For i1 = 1 To 9 'Check Row 5
b(i1) = a(i1 + 36)
Next i1
GoSub 1860: If fl1 = 0 Then GoTo 440
For i1 = 37 To 45 'Check Columns
If a(i1) = a(i1 + 9) Then GoTo 440
If a(i1) = a(i1 + 18) Then GoTo 440
If a(i1) = a(i1 + 27) Then GoTo 440
If a(i1) = a(i1 + 36) Then GoTo 440
Next i1
' Row 6
a(36) = s1 / 3 - a(45) - a(54)
If a(36) < m1 Or a(36) > m2 Then GoTo 440
a(35) = s1 / 3 - a(44) - a(53)
If a(35) < m1 Or a(35) > m2 Then GoTo 440
a(34) = s1 / 3 - a(35) - a(36)
If a(34) < m1 Or a(34) > m2 Then GoTo 440
a(33) = s1 / 3 - a(42) - a(51)
If a(33) < m1 Or a(33) > m2 Then GoTo 440
If a(33) = a(41) Or a(33) = a(49) Or a(33) = a(57) Or a(33) = a(65) Or a(33) = a(73) Then GoTo 440
a(32) = s1 / 3 - a(41) - a(50)
If a(32) < m1 Or a(32) > m2 Then GoTo 440
a(31) = s1 / 3 - a(32) - a(33)
If a(31) < m1 Or a(31) > m2 Then GoTo 440
If a(31) = a(41) Or a(31) = a(51) Or a(31) = a(61) Or a(31) = a(71) Or a(31) = a(81) Then GoTo 440
a(30) = s1 / 3 - a(39) - a(48)
If a(30) < m1 Or a(30) > m2 Then GoTo 440
a(29) = s1 / 3 - a(38) - a(47)
If a(29) < m1 Or a(29) > m2 Then GoTo 440
a(28) = s1 / 3 - a(29) - a(30)
If a(28) < m1 Or a(28) > m2 Then GoTo 440
For i1 = 1 To 9 'Check Row 6
b(i1) = a(i1 + 27)
Next i1
GoSub 1860: If fl1 = 0 Then GoTo 440
For i1 = 28 To 36 'Check Columns
If a(i1) = a(i1 + 9) Then GoTo 440
If a(i1) = a(i1 + 18) Then GoTo 440
If a(i1) = a(i1 + 27) Then GoTo 440
If a(i1) = a(i1 + 36) Then GoTo 440
If a(i1) = a(i1 + 45) Then GoTo 440
Next i1
' Row 7
For j27 = m1 To m2 'a(27)
a(27) = j27
If a(27) = a(45) Or a(27) = a(54) Or a(27) = a(63) Or a(27) = a(72) Or a(27) = a(81) Then GoTo 270
If a(27) = a(36) Then GoTo 270
If a(27) = a(75) Then GoTo 270
For j26 = m1 To m2 'a(26)
a(26) = j26
If a(26) = a(27) Then GoTo 260
If a(26) = a(44) Or a(26) = a(53) Or a(26) = a(62) Or a(26) = a(71) Or a(26) = a(80) Then GoTo 260
If a(26) = a(35) Then GoTo 260
If a(26) = a(66) Then GoTo 260
a(25) = s1 / 3 - a(26) - a(27)
If a(25) < m1 Or a(25) > m2 Then GoTo 260
If a(25) = a(41) Or a(25) = a(49) Or a(25) = a(57) Or a(25) = a(65) Or a(25) = a(73) Then GoTo 260
a(24) = a(27) + a(78) - a(81)
If a(24) < m1 Or a(24) > m2 Then GoTo 260
a(23) = a(26) + a(77) - a(80)
If a(23) < m1 Or a(23) > m2 Then GoTo 260
a(22) = s1 / 3 - a(23) - a(24)
If a(22) < m1 Or a(22) > m2 Then GoTo 260
a(21) = a(27) + a(75) - a(81)
If a(21) < m1 Or a(21) > m2 Then GoTo 260
If a(21) = a(41) Or a(21) = a(51) Or a(21) = a(61) Or a(21) = a(71) Or a(21) = a(81) Then GoTo 260
a(20) = a(26) + a(74) - a(80)
If a(20) < m1 Or a(20) > m2 Then GoTo 260
a(19) = s1 / 3 - a(20) - a(21)
If a(19) < m1 Or a(19) > m2 Then GoTo 260
For i1 = 1 To 9 'Check Row 7
b(i1) = a(i1 + 18)
Next i1
GoSub 1860: If fl1 = 0 Then GoTo 260
For i1 = 19 To 27 'Check Columns
If a(i1) = a(i1 + 9) Then GoTo 260
If a(i1) = a(i1 + 18) Then GoTo 260
If a(i1) = a(i1 + 27) Then GoTo 260
If a(i1) = a(i1 + 36) Then GoTo 260
If a(i1) = a(i1 + 45) Then GoTo 260
If a(i1) = a(i1 + 54) Then GoTo 260
Next i1
' Row 8
a(18) = s1 + a(19) - a(21) - a(45) - a(53) - 2 * a(54) - a(66) - a(69) + a(72) - a(77) - 2 * a(78)
If a(18) < m1 Or a(18) > m2 Then GoTo 260
If a(18) = a(74) Then GoTo 260
a(17) = s1 / 3 - a(44) - a(65) - a(68) + a(71)
If a(17) < m1 Or a(17) > m2 Then GoTo 260
If a(17) = a(65) Then GoTo 260
a(16) = s1 / 3 - a(17) - a(18)
If a(16) < m1 Or a(16) > m2 Then GoTo 260
a(15) = a(18) + a(69) - a(72)
If a(15) < m1 Or a(15) > m2 Then GoTo 260
a(14) = s1 / 3 - a(44) - a(65)
If a(14) < m1 Or a(14) > m2 Then GoTo 260
a(13) = s1 / 3 - a(14) - a(15)
If a(13) < m1 Or a(13) > m2 Then GoTo 260
a(12) = a(15) + a(66) - a(69)
If a(12) < m1 Or a(12) > m2 Then GoTo 260
a(11) = s1 / 3 - a(44) - a(68)
If a(11) < m1 Or a(11) > m2 Then GoTo 260
a(10) = s1 / 3 - a(11) - a(12)
If a(10) < m1 Or a(10) > m2 Then GoTo 260
' Row 9
a(9) = s1 / 3 - a(18) - a(27)
If a(9) < m1 Or a(9) > m2 Then GoTo 260
a(8) = s1 / 3 - a(17) - a(26)
If a(8) < m1 Or a(8) > m2 Then GoTo 260
a(7) = s1 / 3 - a(8) - a(9)
If a(7) < m1 Or a(7) > m2 Then GoTo 260
a(6) = s1 / 3 - a(15) - a(24)
If a(6) < m1 Or a(6) > m2 Then GoTo 260
a(5) = s1 / 3 - a(14) - a(23)
If a(5) < m1 Or a(5) > m2 Then GoTo 260
a(4) = s1 / 3 - a(5) - a(6)
If a(4) < m1 Or a(4) > m2 Then GoTo 260
a(3) = s1 / 3 - a(12) - a(21)
If a(3) < m1 Or a(3) > m2 Then GoTo 260
a(2) = s1 / 3 - a(11) - a(20)
If a(2) < m1 Or a(2) > m2 Then GoTo 260
a(1) = s1 / 3 - a(2) - a(3)
If a(1) < m1 Or a(1) > m2 Then GoTo 260
' Exclude solutions with identical numbers in rows, columns, diagonals, sub squares (9)
GoSub 1800: If fl1 = 0 Then GoTo 5
GoSub 1500: If fl1 = 0 Then GoTo 5 'Check Self Orthogonal
n9 = n9 + 1
' Cells(3, 1).Value = n9 'Counting
' GoSub 2650 'Print results (squares)
GoSub 2645 'Print results (selected numbers)
''End
5
260 Next j26
270 Next j27
440 Next j44
450 Next j45
530 Next j53
540 Next j54
650 Next j65
660 Next j66
680 Next j68
690 Next j69
710 Next j71
720 Next j72
740 Next j74
750 Next j75
770 Next j77
780 Next j78
800 Next j80
810 Next j81
t2 = Timer
t10 = Str(t2 - t1) + " sec., " + Str(n9) + " Solutions for sum" + Str(s1)
y = MsgBox(t10, 0, "Routine SudSqr9e")
End
' Exclude solutions with identical numbers in rows, columns, diagonals, sub squares (9)
1800 fl1 = 1
' Rows
i1 = -8
For i0 = 1 To 9
i1 = i1 + 9
b(1) = a(i1): b(2) = a(i1 + 1): b(3) = a(i1 + 2): b(4) = a(i1 + 3): b(5) = a(i1 + 4)
b(6) = a(i1 + 5): b(7) = a(i1 + 6): b(8) = a(i1 + 7): b(9) = a(i1 + 8)
GoSub 1860: If fl1 = 0 Then Return
Next i0
' Columns
i1 = 0
For i0 = 1 To 9
i1 = i1 + 1
b(1) = a(i1): b(2) = a(i1 + 9): b(3) = a(i1 + 18): b(4) = a(i1 + 27): b(5) = a(i1 + 36)
b(6) = a(i1 + 45): b(7) = a(i1 + 54): b(8) = a(i1 + 63): b(9) = a(i1 + 72)
GoSub 1860: If fl1 = 0 Then Return
Next i0
' Main Diagonals
b(1) = a(1): b(2) = a(11): b(3) = a(21): b(4) = a(31): b(5) = a(41): b(6) = a(51): b(7) = a(61): b(8) = a(71): b(9) = a(81):
GoSub 1860: If fl1 = 0 Then Return
b(1) = a(9): b(2) = a(17): b(3) = a(25): b(4) = a(33): b(5) = a(41): b(6) = a(49): b(7) = a(57): b(8) = a(65): b(9) = a(73):
GoSub 1860: If fl1 = 0 Then Return
Return
1860 fl1 = 1
For j1 = 1 To 9
b20 = b(j1)
For j2 = (1 + j1) To 9
If b20 = b(j2) Then fl1 = 0: Return
Next j2
Next j1
Return
1500 fl1 = 1
' Transpose a()
i3 = 0: Erase a0
For i1 = 1 To 9
For i2 = 1 To 9
i3 = i3 + 1
a0(i1, i2) = a(i3)
Next i2
Next i1
i3 = 0:
For i1 = 1 To 9
For i2 = 1 To 9
i3 = i3 + 1
b2(i3) = a0(i2, i1)
Next i2
Next i1
' Calculate c2()
Erase c2
For i1 = 1 To 81
c2(i1) = 9 * a(i1) + b2(i1) + 1
Next i1
fl1 = 1: n20 = 0
For j1 = 1 To 81
a20 = c2(j1):
For j2 = (1 + j1) To 81
If a20 = c2(j2) Then fl1 = 0: Return
Next j2
1510 Next j1
Return
' Print results (selected numbers)
2645 For i1 = 1 To 81
Cells(n9, i1).Value = a(i1)
Next i1
Cells(n9, 82).Value = n9
Cells(1, 83).Value = n9
Return
' Print results (squares)
2650 n2 = n2 + 1
If n2 = 5 Then
n2 = 1: k1 = k1 + 10: k2 = 1
Else
If n9 > 1 Then k2 = k2 + 10
End If
'' Cells(k1, k2 + 1).Select
Cells(k1, k2 + 1).Font.Color = -4165632
Cells(k1, k2 + 1).Value = CStr(n9)
i3 = 0
For i1 = 1 To 9
For i2 = 1 To 9
i3 = i3 + 1
Cells(k1 + i1, k2 + i2).Value = a(i3)
Next i2
Next i1
Return
End Sub