ALS reduction methods

Programs which generate, solve, and analyze Sudoku puzzles

ALS reduction methods

Postby Wepwawet » Tue Sep 30, 2025 10:32 am

When programming my ALS algorithms, I find it often identifies millions of ALS's in a puzzle, not only does this create time issues, but sometimes the program will run out of memory. Can anyone suggest reduction methods that I should consider to overcome these volumes of data.
Wept
User avatar
Wepwawet
 
Posts: 34
Joined: 19 November 2019

Re: ALS reduction methods

Postby blue » Tue Sep 30, 2025 3:33 pm

For 9x9 sudoku, there can't be more than 3*9*(2^9 - 2) = 13770 of them.
  • 3 house types
  • 9 houses of each type
  • 510 cell sets with 1 <= size <= 8
blue
 
Posts: 1085
Joined: 11 March 2013

Re: ALS reduction methods

Postby StrmCkr » Wed Oct 01, 2025 3:28 am

Think hes refering to chaining ~

Probably an issue with storing it as strong links by sector

As a size 2/3 als can be located in multiple fixed sectors by id

R1c12 for example is box1, r1 for the same set

Which means its a "new" link in terms of code cycling unless you flag it with a id code to skip duplicates

My code has fancy filters to id stuff correctly in a power set generator which also has (dof) to avoid duplicates
And can filter out locked sets (0 dof)

There is millions of als chains on some grids~
Which is why some perfer to limit depth of bfs/dfs code
Or apply alsxz /xy/chains in order after subsets are applied to reduce the number of finds.

Filter to keep only productive chains.

Changing search to use fishing methods for als is also potentially easier/faster?
als is exactly like almost fish ~
Some do, some teach, the rest look it up.
stormdoku
User avatar
StrmCkr
 
Posts: 1473
Joined: 05 September 2006

Re: ALS reduction methods

Postby Wepwawet » Thu Oct 02, 2025 12:37 am

Thanks, and yes, I was referring to chaining, and my code limits the chain's length to 8. I will look into the Almost Fish angle (excuse the pun), as to date, I have only implemented regular and finned fish into my solver (not sure, if that encompasses, all Almost Fish).
Last edited by Wepwawet on Thu Oct 02, 2025 4:16 am, edited 2 times in total.
Wept
User avatar
Wepwawet
 
Posts: 34
Joined: 19 November 2019

Re: ALS reduction methods

Postby Wepwawet » Thu Oct 02, 2025 2:14 am

Regarding the chaining algorithm that I currently employ, I have the program set up to find all unique ALS, those that are confined to the same row or column within the same block are checked for duplication against any other ALS that are restricted to the same block. I do not apply the ALS algorithms until later on in the solver, when the average number of ALS's present per puzzle, is in the ball park of about 230. From this base, I start to concatenate one ALS onto another, building the chain's length, and at anytime, if a chain leads to an elimination, then it is processed and continuance of the algorithm is ceased, however, if the chain is unproductive, then that chain forms the base for potentially further expansion in length, by appending to it, one of the primary ALS's. At each expansion of the chain length, duplicates are weeded out. This is the set up that is leading to the problems that I mentioned in the original post.

Any comments welcome.
Wept
User avatar
Wepwawet
 
Posts: 34
Joined: 19 November 2019

Re: ALS reduction methods

Postby StrmCkr » Thu Oct 02, 2025 6:54 pm

Code: Select all
.---------------------------------.---------------------------------.---------------------------------.
| 123456789  123456789  123456789 | 123456789  123456789  123456789 | 123456789  123456789  123456789 |
| 123456789  12         123456789 | 123456789  23         123456789 | 123456789  123456789  123456789 |
| 123456789  123456789  123456789 | 123456789  123456789  123456789 | 123456789  123456789  123456789 |
:---------------------------------+---------------------------------+---------------------------------:
| 123456789  123456789  123456789 | 123456789  123456789  123456789 | 123456789  123456789  123456789 |
| 123456789  14         123456789 | 123456789  34         123456789 | 123456789  123456789  123456789 |
| 123456789  123456789  123456789 | 123456789  123456789  123456789 | 123456789  123456789  123456789 |
:---------------------------------+---------------------------------+---------------------------------:
| 123456789  123456789  123456789 | 123456789  123456789  123456789 | 123456789  123456789  123456789 |
| 123456789  123456789  123456789 | 123456789  123456789  123456789 | 123456789  123456789  123456789 |
| 123456789  123456789  123456789 | 123456789  123456789  123456789 | 123456789  123456789  123456789 |
'---------------------------------'---------------------------------'---------------------------------'

it could be a memory limit caused by re visiting nodes already used and infinity looping~ this grid should be able to test for that issue

each one of these als nodes if you have nodals listed by sector generation these would appear Three times! : for Row/Col/Box

to fix that issue in my code i added a Cell positional power set check so that if all the cells land in a box ~ that's the sector i key it to.
see working code added for clarity // maybee.

my code has the following output on this grid:

WXYZ - Ring: A=r25c2 {124}, B=r25c5 {234}, X:(AB=4), (BA=2) => r5c1346789 <> 4; r1346789c5 <> 3; r2c1346789 <> 2; r1346789c2 <> 1
WXYZ - Ring: A=r2c25 {123}, B=r5c25 {134}, X:(AB=3), (BA=1) => r5c1346789 <> 4; r1346789c5 <> 3; r2c1346789 <> 2; r1346789c2 <> 1
WXYZ - Wing: A=r2c25 {123}, B=r5c25 {134}, X:(AB=1), Z:(AB=3) => r1346789c5 <> 3
WXYZ - Wing: A=r25c2 {124}, B=r25c5 {234}, X:(AB=4), Z:(AB=2) => r2c1346789 <> 2
WXYZ - Wing: A=r2c25 {123}, B=r5c25 {134}, X:(AB=3), Z:(AB=1) => r1346789c2 <> 1
WXYZ - Wing: A=r25c2 {124}, B=r25c5 {234}, X:(AB=2), Z:(AB=4) => r5c1346789 <> 4
WXYZ - Wing: A=r25c2 {124}, B=r25c5 {234}, X:(AB=2), Z:(AB=4) => r5c1346789 <> 4
ALS - Ring: (1)r2c2=(32)r2c25-(2)r2c5=(43)r25c5-(3)r5c5=(14)r5c25-(4)r5c2=(21)r25c2-(1)r2c2 => r5c1346789 <> 4; r1346789c5 <> 3; r2c1346789 <> 2; r1346789c2 <> 1
ALS - Chain: (3)r2c5=(12)r2c25-(2)r2c2=(41)r25c2-(1)r5c2=(34)r5c25-(4)r5c5=(23)r25c5 => r1346789c5 <> 3; r2c1346789 <> 2
ALS - Chain: (3)r25c5=(243)r25c5-(3)r2c5=(12)r2c25-(2)r2c2=(41)r25c2-(1)r5c2=(34)r5c25 => r5c1346789 <> 4; r1346789c5 <> 3
ALS - Chain: (2)r2c2=(41)r25c2-(1)r5c2=(34)r5c25-(4)r5c5=(23)r25c5-(3)r2c5=(12)r2c25 => r2c1346789 <> 2; r1346789c2 <> 1
ALS - Chain: (2)r2c25=(132)r2c25-(2)r2c2=(41)r25c2-(1)r5c2=(34)r5c25-(4)r5c5=(23)r25c5 => r1346789c5 <> 3; r2c1346789 <> 2
ALS - Chain: (1)r2c2=(32)r2c25-(2)r2c5=(43)r25c5-(3)r5c5=(14)r5c25-(4)r5c2=(12)r25c2 => r2c1346789 <> 2; r1346789c2 <> 1
ALS - Chain: (1)r25c2=(241)r25c2-(1)r2c2=(32)r2c25-(2)r2c5=(43)r25c5-(3)r5c5=(14)r5c25 => r5c1346789 <> 4; r1346789c2 <> 1
ALS - Chain: (4)r5c2=(21)r25c2-(1)r2c2=(32)r2c25-(2)r2c5=(43)r25c5-(3)r5c5=(14)r5c25 => r5c1346789 <> 4; r1346789c2 <> 1
ALS - Chain: (4)r5c25=(134)r5c25-(4)r5c2=(21)r25c2-(1)r2c2=(32)r2c25-(2)r2c5=(34)r25c5 => r5c1346789 <> 4; r1346789c5 <> 3
ALS - Chain: (3=2)r2c5-(2=1)r2c2-(1=4)r5c2-(4)r5c5=(23)r25c5 => r1346789c5 <> 3
ALS - Chain: (3)r25c5=(42)r25c5-(2=1)r2c2-(1=4)r5c2-(4=3)r5c5 => r1346789c5 <> 3
ALS - Chain: (2=1)r2c2-(1=4)r5c2-(4=3)r5c5-(3)r2c5=(12)r2c25 => r2c1346789 <> 2
ALS - Chain: (2)r2c25=(31)r2c25-(1=4)r5c2-(4=3)r5c5-(3=2)r2c5 => r2c1346789 <> 2
ALS - Chain: (1=2)r2c2-(2=3)r2c5-(3=4)r5c5-(4)r5c2=(12)r25c2 => r1346789c2 <> 1
ALS - Chain: (1)r25c2=(42)r25c2-(2=3)r2c5-(3=4)r5c5-(4=1)r5c2 => r1346789c2 <> 1
ALS - Chain: (4=1)r5c2-(1=2)r2c2-(2=3)r2c5-(3)r5c5=(14)r5c25 => r5c1346789 <> 4
ALS - Chain: (4)r5c25=(31)r5c25-(1=2)r2c2-(2=3)r2c5-(3=4)r5c5 => r5c1346789 <> 4
ALS - Chain: (3=2)r2c5-(2=1)r2c2-(1)r5c2=(34)r5c25-(4)r5c5=(23)r25c5 => r1346789c5 <> 3
ALS - Chain: (3)r25c5=(243)r25c5-(3)r2c5=(21)r2c25-(1=4)r5c2-(4=3)r5c5 => r1346789c5 <> 3
ALS - Chain: (2=1)r2c2-(1=4)r5c2-(4)r5c5=(23)r25c5-(3)r2c5=(12)r2c25 => r2c1346789 <> 2
ALS - Chain: (2)r2c25=(132)r2c25-(2)r2c2=(14)r25c2-(4=3)r5c5-(3=2)r2c5 => r2c1346789 <> 2
ALS - Chain: (1=2)r2c2-(2=3)r2c5-(3)r5c5=(14)r5c25-(4)r5c2=(12)r25c2 => r1346789c2 <> 1
ALS - Chain: (1)r25c2=(241)r25c2-(1)r2c2=(23)r2c25-(3=4)r5c5-(4=1)r5c2 => r1346789c2 <> 1
ALS - Chain: (4=1)r5c2-(1=2)r2c2-(2)r2c5=(43)r25c5-(3)r5c5=(14)r5c25 => r5c1346789 <> 4
ALS - Chain: (4)r5c25=(134)r5c25-(4)r5c2=(12)r25c2-(2=3)r2c5-(3=4)r5c5 => r5c1346789 <> 4
ALS - Chain: (3=2)r2c5-(2)r2c2=(41)r25c2-(1)r5c2=(34)r5c25-(4)r5c5=(23)r25c5 => r1346789c5 <> 3
ALS - Chain: (3)r25c5=(24)r25c5-(4=1)r5c2-(1=2)r2c2-(2)r2c5=(34)r25c5 => r1346789c5 <> 3
ALS - Chain: (3)r25c5=(42)r25c5-(2=1)r2c2-(1=4)r5c2-(4)r5c5=(23)r25c5 => r1346789c5 <> 3
ALS - Chain: (3)r25c5=(243)r25c5-(3)r2c5=(12)r2c25-(2)r2c2=(14)r25c2-(4=3)r5c5 => r1346789c5 <> 3
ALS - Chain: (2=1)r2c2-(1)r5c2=(34)r5c25-(4)r5c5=(23)r25c5-(3)r2c5=(12)r2c25 => r2c1346789 <> 2
ALS - Chain: (2)r2c25=(132)r2c25-(2)r2c2=(41)r25c2-(1)r5c2=(43)r5c25-(3=2)r2c5 => r2c1346789 <> 2
ALS - Chain: (2)r2c25=(31)r2c25-(1=4)r5c2-(4=3)r5c5-(3)r2c5=(12)r2c25 => r2c1346789 <> 2
ALS - Chain: (1=2)r2c2-(2)r2c5=(43)r25c5-(3)r5c5=(14)r5c25-(4)r5c2=(12)r25c2 => r1346789c2 <> 1
ALS - Chain: (2)r2c25=(13)r2c25-(3=4)r5c5-(4=1)r5c2-(1)r2c2=(23)r2c25 => r2c1346789 <> 2
ALS - Chain: (1)r25c2=(24)r25c2-(4=3)r5c5-(3=2)r2c5-(2)r2c2=(14)r25c2 => r1346789c2 <> 1
ALS - Chain: (1)r25c2=(241)r25c2-(1)r2c2=(32)r2c25-(2)r2c5=(34)r25c5-(4=1)r5c2 => r1346789c2 <> 1
ALS - Chain: (1)r25c2=(42)r25c2-(2=3)r2c5-(3=4)r5c5-(4)r5c2=(12)r25c2 => r1346789c2 <> 1
ALS - Chain: (4=1)r5c2-(1)r2c2=(32)r2c25-(2)r2c5=(43)r25c5-(3)r5c5=(14)r5c25 => r5c1346789 <> 4
ALS - Chain: (4)r5c25=(31)r5c25-(1=2)r2c2-(2=3)r2c5-(3)r5c5=(14)r5c25 => r5c1346789 <> 4
ALS - Chain: (4)r5c25=(134)r5c25-(4)r5c2=(21)r25c2-(1)r2c2=(23)r2c25-(3=4)r5c5 => r5c1346789 <> 4
ALS - Chain: (4)r5c25=(13)r5c25-(3=2)r2c5-(2=1)r2c2-(1)r5c2=(34)r5c25 => r5c1346789 <> 4
ALS - Chain: (3)r25c5=(24)r25c5-(4=1)r5c2-(1)r2c2=(32)r2c25-(2)r2c5=(34)r25c5 => r1346789c5 <> 3
ALS - Chain: (3)r25c5=(243)r25c5-(3)r5c5=(41)r5c25-(1=2)r2c2-(2)r2c5=(34)r25c5 => r1346789c5 <> 3
ALS - Chain: (3)r25c5=(42)r25c5-(2=1)r2c2-(1)r5c2=(34)r5c25-(4)r5c5=(23)r25c5 => r1346789c5 <> 3
ALS - Chain: (3)r25c5=(243)r25c5-(3)r2c5=(21)r2c25-(1=4)r5c2-(4)r5c5=(23)r25c5 => r1346789c5 <> 3
ALS - Chain: (2)r2c25=(132)r2c25-(2)r2c2=(14)r25c2-(4=3)r5c5-(3)r2c5=(12)r2c25 => r2c1346789 <> 2
ALS - Chain: (2)r2c25=(31)r2c25-(1=4)r5c2-(4)r5c5=(23)r25c5-(3)r2c5=(12)r2c25 => r2c1346789 <> 2
ALS - Chain: (2)r2c25=(13)r2c25-(3=4)r5c5-(4)r5c2=(21)r25c2-(1)r2c2=(23)r2c25 => r2c1346789 <> 2
ALS - Chain: (2)r2c25=(132)r2c25-(2)r2c5=(34)r25c5-(4=1)r5c2-(1)r2c2=(23)r2c25 => r2c1346789 <> 2
ALS - Chain: (1)r25c2=(24)r25c2-(4=3)r5c5-(3)r2c5=(12)r2c25-(2)r2c2=(14)r25c2 => r1346789c2 <> 1
ALS - Chain: (1)r25c2=(241)r25c2-(1)r5c2=(43)r5c25-(3=2)r2c5-(2)r2c2=(14)r25c2 => r1346789c2 <> 1
ALS - Chain: (1)r25c2=(241)r25c2-(1)r2c2=(23)r2c25-(3=4)r5c5-(4)r5c2=(12)r25c2 => r1346789c2 <> 1
ALS - Chain: (1)r25c2=(42)r25c2-(2=3)r2c5-(3)r5c5=(14)r5c25-(4)r5c2=(12)r25c2 => r1346789c2 <> 1
ALS - Chain: (4)r5c25=(31)r5c25-(1=2)r2c2-(2)r2c5=(43)r25c5-(3)r5c5=(14)r5c25 => r5c1346789 <> 4
ALS - Chain: (4)r5c25=(134)r5c25-(4)r5c2=(12)r25c2-(2=3)r2c5-(3)r5c5=(14)r5c25 => r5c1346789 <> 4
ALS - Chain: (4)r5c25=(13)r5c25-(3=2)r2c5-(2)r2c2=(41)r25c2-(1)r5c2=(34)r5c25 => r5c1346789 <> 4
ALS - Chain: (4)r5c25=(134)r5c25-(4)r5c5=(32)r25c5-(2=1)r2c2-(1)r5c2=(34)r5c25 => r5c1346789 <> 4
ALS - Chain: (3)r25c5=(24)r25c5-(4)r5c2=(21)r25c2-(1)r2c2=(32)r2c25-(2)r2c5=(34)r25c5 => r1346789c5 <> 3
ALS - Chain: (3)r25c5=(243)r25c5-(3)r5c5=(41)r5c25-(1)r2c2=(32)r2c25-(2)r2c5=(34)r25c5 => r1346789c5 <> 3
ALS - Chain: (3)r25c5=(243)r25c5-(3)r5c5=(14)r5c25-(4)r5c2=(12)r25c2-(2)r2c5=(34)r25c5 => r1346789c5 <> 3
ALS - Chain: (3)r25c5=(42)r25c5-(2)r2c2=(41)r25c2-(1)r5c2=(34)r5c25-(4)r5c5=(23)r25c5 => r1346789c5 <> 3
ALS - Chain: (3)r25c5=(243)r25c5-(3)r2c5=(12)r2c25-(2)r2c2=(14)r25c2-(4)r5c5=(23)r25c5 => r1346789c5 <> 3
ALS - Chain: (3)r25c5=(243)r25c5-(3)r2c5=(21)r2c25-(1)r5c2=(34)r5c25-(4)r5c5=(23)r25c5 => r1346789c5 <> 3
ALS - Chain: (2)r2c25=(132)r2c25-(2)r2c2=(14)r25c2-(4)r5c5=(23)r25c5-(3)r2c5=(12)r2c25 => r2c1346789 <> 2
ALS - Chain: (2)r2c25=(132)r2c25-(2)r2c2=(41)r25c2-(1)r5c2=(43)r5c25-(3)r2c5=(12)r2c25 => r2c1346789 <> 2
ALS - Chain: (2)r2c25=(31)r2c25-(1)r5c2=(34)r5c25-(4)r5c5=(23)r25c5-(3)r2c5=(12)r2c25 => r2c1346789 <> 2
ALS - Chain: (2)r2c25=(13)r2c25-(3)r5c5=(14)r5c25-(4)r5c2=(21)r25c2-(1)r2c2=(23)r2c25 => r2c1346789 <> 2
ALS - Chain: (2)r2c25=(132)r2c25-(2)r2c5=(34)r25c5-(4)r5c2=(21)r25c2-(1)r2c2=(23)r2c25 => r2c1346789 <> 2
ALS - Chain: (2)r2c25=(132)r2c25-(2)r2c5=(43)r25c5-(3)r5c5=(41)r5c25-(1)r2c2=(23)r2c25 => r2c1346789 <> 2
ALS - Chain: (1)r25c2=(241)r25c2-(1)r5c2=(43)r5c25-(3)r2c5=(12)r2c25-(2)r2c2=(14)r25c2 => r1346789c2 <> 1
ALS - Chain: (1)r25c2=(241)r25c2-(1)r5c2=(34)r5c25-(4)r5c5=(32)r25c5-(2)r2c2=(14)r25c2 => r1346789c2 <> 1
ALS - Chain: (1)r25c2=(24)r25c2-(4)r5c5=(23)r25c5-(3)r2c5=(12)r2c25-(2)r2c2=(14)r25c2 => r1346789c2 <> 1
ALS - Chain: (1)r25c2=(241)r25c2-(1)r2c2=(23)r2c25-(3)r5c5=(14)r5c25-(4)r5c2=(12)r25c2 => r1346789c2 <> 1
ALS - Chain: (1)r25c2=(241)r25c2-(1)r2c2=(32)r2c25-(2)r2c5=(34)r25c5-(4)r5c2=(12)r25c2 => r1346789c2 <> 1
ALS - Chain: (1)r25c2=(42)r25c2-(2)r2c5=(43)r25c5-(3)r5c5=(14)r5c25-(4)r5c2=(12)r25c2 => r1346789c2 <> 1
ALS - Chain: (4)r5c25=(31)r5c25-(1)r2c2=(32)r2c25-(2)r2c5=(43)r25c5-(3)r5c5=(14)r5c25 => r5c1346789 <> 4
ALS - Chain: (4)r5c25=(134)r5c25-(4)r5c2=(21)r25c2-(1)r2c2=(23)r2c25-(3)r5c5=(14)r5c25 => r5c1346789 <> 4
ALS - Chain: (4)r5c25=(134)r5c25-(4)r5c2=(12)r25c2-(2)r2c5=(43)r25c5-(3)r5c5=(14)r5c25 => r5c1346789 <> 4
ALS - Chain: (4)r5c25=(13)r5c25-(3)r2c5=(12)r2c25-(2)r2c2=(41)r25c2-(1)r5c2=(34)r5c25 => r5c1346789 <> 4
ALS - Chain: (4)r5c25=(134)r5c25-(4)r5c5=(32)r25c5-(2)r2c2=(41)r25c2-(1)r5c2=(34)r5c25 => r5c1346789 <> 4
ALS - Chain: (4)r5c25=(134)r5c25-(4)r5c5=(23)r25c5-(3)r2c5=(21)r2c25-(1)r5c2=(34)r5c25 => r5c1346789 <> 4
ALS - Chain: (3)r25c5=(243)r25c5-(3)r5c5=(14)r5c25-(4)r5c2=(21)r25c2-(1)r2c2=(32)r2c25-(2)r2c5=(34)r25c5 => r1346789c5 <> 3
ALS - Chain: (3)r25c5=(243)r25c5-(3)r2c5=(12)r2c25-(2)r2c2=(41)r25c2-(1)r5c2=(34)r5c25-(4)r5c5=(23)r25c5 => r1346789c5 <> 3
ALS - Chain: (2)r2c25=(132)r2c25-(2)r2c2=(41)r25c2-(1)r5c2=(34)r5c25-(4)r5c5=(23)r25c5-(3)r2c5=(12)r2c25 => r2c1346789 <> 2
ALS - Chain: (2)r2c25=(132)r2c25-(2)r2c5=(43)r25c5-(3)r5c5=(14)r5c25-(4)r5c2=(21)r25c2-(1)r2c2=(23)r2c25 => r2c1346789 <> 2
ALS - Chain: (1)r25c2=(241)r25c2-(1)r5c2=(34)r5c25-(4)r5c5=(23)r25c5-(3)r2c5=(12)r2c25-(2)r2c2=(14)r25c2 => r1346789c2 <> 1
ALS - Chain: (1)r25c2=(241)r25c2-(1)r2c2=(32)r2c25-(2)r2c5=(43)r25c5-(3)r5c5=(14)r5c25-(4)r5c2=(12)r25c2 => r1346789c2 <> 1
ALS - Chain: (4)r5c25=(134)r5c25-(4)r5c2=(21)r25c2-(1)r2c2=(32)r2c25-(2)r2c5=(43)r25c5-(3)r5c5=(14)r5c25 => r5c1346789 <> 4
ALS - Chain: (4)r5c25=(134)r5c25-(4)r5c5=(23)r25c5-(3)r2c5=(12)r2c25-(2)r2c2=(41)r25c2-(1)r5c2=(34)r5c25 => r5c1346789 <> 4

als dof generator code with skipping functions:

als generator: Show
Code: Select all
package sudoku.DataStorage;

import static sudoku.HelpingTools.SetOps.intersection;

import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

import sudoku.HelpingTools.SetOps;
import sudoku.HelpingTools.Tools;
import sudoku.HelpingTools.cardinals;

public class ALS {

    private static final BitSet DUPLICATES_A = SetOps.fromInts(9, 10, 17, 30, 31, 35, 42, 43, 44);

    private static final BitSet DUPLICATES_B = SetOps.fromInts(45, 109, 128);

    public static int maxSizeDOF = 8; // change back to 8 once done testing basics
    public static int maxSizeFox = 7;
    public int alsSector;
    public int alsSize;
    public int alsFOX;
    public int alsDOF;
    public int PowerSet;
    public BitSet alsDigits;
    public BitSet alsAllCells;
    public List<RCC> rccList;

    public UUID uniqueID;

    public ALS(int alsSector, int alsSize, int alsFOX, BitSet alsDigits, BitSet alsAllCells, int PowerSet, List<RCC> rccList) {
        this.alsSector = alsSector;
        this.alsSize = alsSize;
        this.alsFOX = alsFOX;
        this.alsDOF = alsFOX - alsSize; // Degrees of Freedom = FOX - size

        this.alsDigits = alsDigits;
        this.rccList = rccList;
        this.alsAllCells = alsAllCells;
        this.PowerSet = PowerSet;
        this.uniqueID = UUID.randomUUID();
    }

    public static class RCC {
        @SuppressWarnings("unused")
        public int rccDigit;
        public BitSet rccCells;
        public BitSet rccPotentialElim; // can be null
        public BitSet rccSectors;
        public Object digit;

        public RCC(int rccDigit,
                BitSet rccCells,
                BitSet rccSectors,
                BitSet rccPotentialElim) {
            this.rccDigit = rccDigit;
            this.rccCells = rccCells;
            this.rccSectors = rccSectors;
            this.rccPotentialElim = rccPotentialElim;

        }
    }

    @SuppressWarnings("unchecked")
    public static ALS[] alsConstructor(SBRCGrid sbrc, boolean searchLimit, boolean sizelimit) {

        List<ALS> alsList = new ArrayList<>();
        alsList = new ArrayList<>();

        // als sector to search
        for (int sector = 0; sector < cardinals.secs; sector++) {
            // skip all sectors with less then 2 digits as no als can be found in it.
            // amended this to find all ls and subets no LS exsits with less then 1 digit.
            if (sbrc.sectorN[sector].cardinality() >= 1) {
                // als sector to search by size of the als.
                for (int positionSize = 0; positionSize <= (maxSizeDOF); positionSize++) {

                    // skips naked singles for r/c and makes it look for them in boxes
                    // if (positionSize == 0 && sector < 18) {
                    // continue;
                    // }

                    // Degrees of Freedom <=> freedom of x
                    for (int FoxRange = -1; FoxRange <= (maxSizeFox - positionSize); FoxRange++) {
                        // calculates the size the digits should be for given als size of position, and
                        // the size of FOX
                        int FOX = FoxRange + positionSize + 1;

                        if (searchLimit && (FOX - positionSize) != 1) {
                            continue;
                        }

                        if (sizelimit && (FOX - positionSize > 0)) {
                            continue;
                        }

                        // checks the sector has at least the same number of digits as called by fox to
                        if (sbrc.sectorN[sector].cardinality() >= (FOX + 1)) {

                            // position of the cells given the size

                            for (int PowerSetIndex = Tools.Slist[positionSize]; PowerSetIndex <= Tools.Flist[positionSize]; PowerSetIndex++) {

                                // skip code to remove duplicates: predetermined to have all specifics isolated
                                // to box call

//if the sector is a r/c & the postions land on a sigle r/c for one box:  & the size of position is 3 we skip                                       
                                if (sector < 18 && DUPLICATES_A.get(PowerSetIndex) && positionSize == 1 && FoxRange > -1) {
                                    continue;
                                }
//if the sector is a r/c & the postions land on a single r/c for one  box: & the size of position is 3 we skip   
                                if (sector < 18 && DUPLICATES_B.get(PowerSetIndex) && positionSize == 2 && FoxRange > -1) {
                                    continue;
                                }

                                // {checks that all active cells for the selected set are active}
                                if (SetOps.intersection(sbrc.ComboCell[510],
                                        Tools.combosetS[sector][PowerSetIndex]).equals(Tools.combosetS[sector][PowerSetIndex])) {

                                    if (sbrc.ComboNum[PowerSetIndex][sector].cardinality() == (FOX + 1)) {

                                        // power set to determine the # of digits used of the cells selected
                                        for (int DigitSet = Tools.Slist[FOX]; DigitSet <= Tools.Flist[FOX]; DigitSet++) {

                                            // checks the sector selected to ensure it has all digits

                                            if (SetOps.intersection(sbrc.sectorN[sector], Tools.comboset2[DigitSet]).equals(Tools.comboset2[DigitSet])) {

                                                // digit count matches position size}

                                                if (SetOps.intersection(sbrc.ComboCell[DigitSet],
                                                        Tools.combosetS[sector][PowerSetIndex]).equals(Tools.combosetS[sector][PowerSetIndex])) {

                                                    BitSet alsCells = Tools.combosetS[sector][PowerSetIndex];
                                                    BitSet alsDigits = Tools.comboset2[DigitSet];

                                                    List<RCC> rccList = new ArrayList<>();

                                                    for (int rccDigit = alsDigits.nextSetBit(0); rccDigit >= 0; rccDigit = alsDigits.nextSetBit(rccDigit + 1)) {

                                                        BitSet rccCells = intersection(alsCells, sbrc.digitcell[rccDigit]);
                                                        BitSet RccPotentialElims = Tools.GetPeers2(sbrc, rccDigit, rccCells);

                                                        BitSet targetSector = new BitSet();
                                                        targetSector.set(sector);

                                                        for (int RccSector = Tools.peerRCB[sector].nextSetBit(0); RccSector >= 0; RccSector = Tools.peerRCB[sector].nextSetBit(RccSector + 1)) {
                                                            BitSet locsInSectorB = sbrc.DigitRCB[RccSector][rccDigit];
                                                            if (intersection(rccCells, locsInSectorB).equals(rccCells)) {

                                                                targetSector.set(RccSector);
                                                            }
                                                        }

                                                        RCC entry = new RCC(rccDigit, rccCells, targetSector, RccPotentialElims);
                                                        rccList.add(entry);

                                                    }

                                                    ALS alsEntry = new ALS(sector, (positionSize), (FOX), alsDigits, alsCells, PowerSetIndex, rccList);
                                                    alsList.add(alsEntry);
                                                }

                                            }
                                        }

                                    }
                                }
                            }
                        }
                    }

                }

            }
        }

        return alsList.toArray(ALS[]::new);
    }

    public static void printALS(ALS[] alsLists) {

        for (ALS alsList : alsLists) {
            int alsSector = alsList.alsSector;
            int alsDOf = alsList.alsDOF;
            int size = alsList.alsSize;
            int alsFOX = alsList.alsFOX;
            BitSet alsAllCells = alsList.alsAllCells;
            BitSet digits = alsList.alsDigits;
            List<RCC> rcclisting = alsList.rccList;

            System.out.println("AlsList: DOF(" + alsDOf + ") size(" + size + ") FOX (" + alsFOX + ") cells:" + Tools.GetMutiLocals(alsAllCells) + " als Digits " + Tools.getDigits(digits));

            for (ALS.RCC rcc : rcclisting) {
                int rccdigitsList = rcc.rccDigit;
                BitSet rccCells = rcc.rccCells;
                BitSet potentialElim = rcc.rccPotentialElim;
                BitSet sectors = rcc.rccSectors;

                System.out.println(" RCC: digit = " + (rccdigitsList + 1));
                System.out.println(" rccCells = " + Tools.GetMutiLocals(rccCells));
                System.out.println(" potentialElim = " + Tools.GetMutiLocals(potentialElim));
                System.out.println(" sectors = " + sectors);

            }
        }

    }

    public static String printALS2(ALS als) {
        String export = new String();
        int alsSector = als.alsSector;
        int alsDOf = als.alsDOF;
        int size = als.alsSize;
        int alsFOX = als.alsFOX;
        BitSet alsAllCells = als.alsAllCells;
        BitSet digits = als.alsDigits;
        List<RCC> rcclisting = als.rccList;
        export = export + (" AlsList: DOF(" + alsDOf + ") size(" + size + ") FOX (" + alsFOX + ") cells:" + Tools.GetMutiLocals(alsAllCells) + " als Digits " + Tools.getDigits(digits));

        /*
         * for (ALS_Rebuild_Test.RCC rcc : rcclisting) { int rccdigitsList =
         * rcc.rccDigit; BitSet rccCells = rcc.rccCells; BitSet potentialElim =
         * rcc.rccPotentialElim; BitSet sectors = rcc.rccSectors;
         *
         * export = export + (" RCC: digit = " + (rccdigitsList + 1)); export = export +
         * (" rccCells = " + Tools.GetMutiLocals(rccCells)); export = export +
         * (" potentialElim = " + Tools.GetMutiLocals(potentialElim)); export = export +
         * (" sectors = " + sectors);
         *
         * }
         */
        return export;
    }

    public static String printRCC(List<RCC> RCC) {
        List<RCC> rcclisting = RCC;
        String export = new String();
        for (ALS.RCC rcc : rcclisting) {
            int rccdigitsList = rcc.rccDigit;
            BitSet rccCells = rcc.rccCells;
            BitSet potentialElim = rcc.rccPotentialElim;
            BitSet sectors = rcc.rccSectors;

            export = export + (" RCC: digit = " + (rccdigitsList + 1));
            export = export + (" rccCells = " + Tools.GetMutiLocals(rccCells));
            export = export + (" potentialElim = " + Tools.GetMutiLocals(potentialElim));
            export = export + (" sectors = " + sectors);

        }
        return export;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        ALS that = (ALS) o;
        return alsDOF == that.alsDOF &&
                alsSize == that.alsSize &&
                Objects.equals(alsAllCells, that.alsAllCells) &&
                Objects.equals(alsDigits, that.alsDigits) &&
                Objects.equals(rccList, that.rccList);
    }

    @Override
    public int hashCode() {
        return Objects.hash(alsDOF, alsSize, alsAllCells, alsDigits, rccList);
    }

    public static String printALS3(List<ALS> path) {
        String export = new String();
        for (ALS als : path) {
            int alsSector = als.alsSector;
            int alsDOf = als.alsDOF;
            int size = als.alsSize;
            int alsFOX = als.alsFOX;
            BitSet alsAllCells = als.alsAllCells;
            BitSet digits = als.alsDigits;
            List<RCC> rcclisting = als.rccList;
            export = export + (" AlsList: DOF(" + alsDOf + ") size(" + size + ") FOX (" + alsFOX + ") cells:" + Tools.GetMutiLocals(alsAllCells) + " als Digits " + Tools.getDigits(digits));

            /*
             * for (ALS_Rebuild_Test.RCC rcc : rcclisting) { int rccdigitsList =
             * rcc.rccDigit; BitSet rccCells = rcc.rccCells; BitSet potentialElim =
             * rcc.rccPotentialElim; BitSet sectors = rcc.rccSectors;
             *
             * export = export + (" RCC: digit = " + (rccdigitsList + 1)); export = export +
             * (" rccCells = " + Tools.GetMutiLocals(rccCells)); export = export +
             * (" potentialElim = " + Tools.GetMutiLocals(potentialElim)); export = export +
             * (" sectors = " + sectors);
             *
             * }
             */
        }
        return export;
    }

    public UUID getUniqueId() {
        return uniqueID;
    }

    public BitSet getAlsDigits() {
        return alsDigits;
    }

    public BitSet getAlsAllCells() {
        return alsAllCells;
    }

    public List<RCC> getRccList() {
        return rccList;
    }

    public int getAlsSector() {
        return alsSector;
    }

    public int getAlsSize() {
        return alsSize;
    }

    public int getAlsFOX() {
        return alsFOX;
    }

    public int getAlsDOF() {
        return alsDOF;
    }

    public int getPowerSet() {
        return PowerSet;
    }
}


power set refrence: Show
//the power set is a bitset of "Positions" generated by a specific combination set from size 1-9 via this function. ie 511 combinations.
Code: Select all
 public static void generateCombinations(int n, int k, List<BitSet> result) {
        int[] v = new int[k];

        // Initialize the first combination
        for (int i = 0; i < k; i++) {
            v[i] = i;
        }

        // Generate combinations iteratively in lexicographical order
        do {
            result.add(copyArrayToBitSet(v, k));
        } while (next_combination(v, n, k));
    }
Some do, some teach, the rest look it up.
stormdoku
User avatar
StrmCkr
 
Posts: 1473
Joined: 05 September 2006

Re: ALS reduction methods

Postby StrmCkr » Thu Oct 02, 2025 7:30 pm

the ALS list
RCC is the key not all of them are valid to be useful
all the Cells with this value must land in 1 sector <-

then
you use the RCC"S "Sector" as the linking point and build a list of Weak-inferences

compare the RCC to another ALS
this als has the same RCC Value with the same "sector" and not overlapping Cells
if true this Als node is added as the weak inference

this gives you a list of ALS with a list of weak inferences that can be "walked" in depth or breadth

start at als A -> walk *list of weak inferences*
{a1} -> apply xz rule { a1,a}
-> walk list of {a1}'s weak inferences {b} -> APPLY XY RULE {A,B}, APPLY XZ RULE { B,1A}, check ring rule,
-> walk list of {B} weak inferences {...} repeat till exhaustion

be mindful to not allow reusing nodes~
Some do, some teach, the rest look it up.
stormdoku
User avatar
StrmCkr
 
Posts: 1473
Joined: 05 September 2006


Return to Software