├── TwoPhaseSolver
├── tables
│ ├── move
│ │ ├── co_move
│ │ ├── cp_move
│ │ ├── ds_move
│ │ ├── eo_move
│ │ ├── ep2_move
│ │ ├── ud_move
│ │ ├── uds_move
│ │ └── us_move
│ ├── other
│ │ ├── combi
│ │ └── ep2_merge
│ └── prune
│ │ ├── co_ud_prun
│ │ ├── cp_ud2_prun
│ │ ├── eo_ud_prun
│ │ └── ep2_ud2_prun
├── Constants.cs
├── PruneTable.cs
├── Properties
│ └── AssemblyInfo.cs
├── BinLoad.cs
├── TwoPhaseSolver.csproj
├── Tools.cs
├── Move.cs
├── Coords.cs
├── Cube.cs
└── Search.cs
├── SolverTest
├── App.config
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
└── SolverTest.csproj
├── LICENSE
├── TwoPhaseSolver.sln
├── README.md
├── .gitattributes
└── .gitignore
/TwoPhaseSolver/tables/move/co_move:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tremwil/TwoPhaseSolver/HEAD/TwoPhaseSolver/tables/move/co_move
--------------------------------------------------------------------------------
/TwoPhaseSolver/tables/move/cp_move:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tremwil/TwoPhaseSolver/HEAD/TwoPhaseSolver/tables/move/cp_move
--------------------------------------------------------------------------------
/TwoPhaseSolver/tables/move/ds_move:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tremwil/TwoPhaseSolver/HEAD/TwoPhaseSolver/tables/move/ds_move
--------------------------------------------------------------------------------
/TwoPhaseSolver/tables/move/eo_move:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tremwil/TwoPhaseSolver/HEAD/TwoPhaseSolver/tables/move/eo_move
--------------------------------------------------------------------------------
/TwoPhaseSolver/tables/move/ep2_move:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tremwil/TwoPhaseSolver/HEAD/TwoPhaseSolver/tables/move/ep2_move
--------------------------------------------------------------------------------
/TwoPhaseSolver/tables/move/ud_move:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tremwil/TwoPhaseSolver/HEAD/TwoPhaseSolver/tables/move/ud_move
--------------------------------------------------------------------------------
/TwoPhaseSolver/tables/move/uds_move:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tremwil/TwoPhaseSolver/HEAD/TwoPhaseSolver/tables/move/uds_move
--------------------------------------------------------------------------------
/TwoPhaseSolver/tables/move/us_move:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tremwil/TwoPhaseSolver/HEAD/TwoPhaseSolver/tables/move/us_move
--------------------------------------------------------------------------------
/TwoPhaseSolver/tables/other/combi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tremwil/TwoPhaseSolver/HEAD/TwoPhaseSolver/tables/other/combi
--------------------------------------------------------------------------------
/TwoPhaseSolver/tables/other/ep2_merge:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tremwil/TwoPhaseSolver/HEAD/TwoPhaseSolver/tables/other/ep2_merge
--------------------------------------------------------------------------------
/TwoPhaseSolver/tables/prune/co_ud_prun:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tremwil/TwoPhaseSolver/HEAD/TwoPhaseSolver/tables/prune/co_ud_prun
--------------------------------------------------------------------------------
/TwoPhaseSolver/tables/prune/cp_ud2_prun:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tremwil/TwoPhaseSolver/HEAD/TwoPhaseSolver/tables/prune/cp_ud2_prun
--------------------------------------------------------------------------------
/TwoPhaseSolver/tables/prune/eo_ud_prun:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tremwil/TwoPhaseSolver/HEAD/TwoPhaseSolver/tables/prune/eo_ud_prun
--------------------------------------------------------------------------------
/TwoPhaseSolver/tables/prune/ep2_ud2_prun:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tremwil/TwoPhaseSolver/HEAD/TwoPhaseSolver/tables/prune/ep2_ud2_prun
--------------------------------------------------------------------------------
/SolverTest/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/TwoPhaseSolver/Constants.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace TwoPhaseSolver
8 | {
9 | public struct Constants
10 | {
11 | public const int N_CO = 2187; // 3^7
12 | public const int N_EO = 2048; // 2^12
13 | public const int N_UD = 495; // 12! / (4! * 8!)
14 |
15 | public const int N_CP = 40320; // 8!
16 | public const int N_EP2 = 40320; // 8!
17 | public const int N_UDS = 11880; // 12! / 8!
18 | public const int N_UD2 = 24; // 4!
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 William Tremblay
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/SolverTest/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using TwoPhaseSolver;
3 |
4 | namespace SolverTest
5 | {
6 | class Program
7 | {
8 | static void Main(string[] args)
9 | {
10 | // Just solve a random cube with some pattern.
11 | Cube c = Move.randmove(200).apply(new Cube());
12 | Move pattern;
13 |
14 | // BEST. RANDOM. GEN. EVER. (actually not that bad,
15 | // since you'd have to time yourself with 100nanosecond precision
16 | if ((DateTime.Now.Ticks & 1) == 0)
17 | {
18 | pattern = Move.None;
19 | Console.WriteLine("No pattern this time...");
20 | }
21 | else
22 | {
23 | pattern = Move.randmove(20);
24 | Console.WriteLine("Pattern is {0}", pattern);
25 | }
26 |
27 | // Do the actual solve while printing what is happening
28 | Search.patternSolve(c, pattern, 22, printInfo: true);
29 |
30 | // End
31 | Console.Write("Press any key to continue...");
32 | Console.Read();
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/TwoPhaseSolver/PruneTable.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace TwoPhaseSolver
8 | {
9 | public class PruneTable
10 | {
11 | byte[] bytes;
12 |
13 | public PruneTable(int size)
14 | {
15 | bytes = new byte[size / 2];
16 | }
17 |
18 | public PruneTable(byte[] bytes)
19 | {
20 | this.bytes = bytes;
21 | }
22 |
23 | public byte this[int index]
24 | {
25 | get
26 | {
27 | if ((index & 1) == 1) { return (byte)((bytes[index / 2] & 0xf0) >> 4); }
28 | else { return (byte)(bytes[index / 2] & 0x0f); }
29 | }
30 | set
31 | {
32 | if ((index & 1) == 1) { bytes[index / 2] &= (byte)(0x0f | (value << 4)); }
33 | else { bytes[index / 2] &= (byte)(value | 0xf0); }
34 | }
35 | }
36 |
37 | // Prune tables
38 |
39 | public static readonly PruneTable pruneCO = BinLoad.loadPruneTable("tables\\prune\\co_ud_prun");
40 | public static readonly PruneTable pruneEO = BinLoad.loadPruneTable("tables\\prune\\eo_ud_prun");
41 |
42 | public static readonly PruneTable pruneCP = BinLoad.loadPruneTable("tables\\prune\\cp_ud2_prun");
43 | public static readonly PruneTable pruneEP2 = BinLoad.loadPruneTable("tables\\prune\\ep2_ud2_prun");
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/SolverTest/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("SolverTest")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("SolverTest")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("ea6d133f-b24e-42b6-826e-c18e6a6bdd61")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/TwoPhaseSolver.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25123.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TwoPhaseSolver", "TwoPhaseSolver\TwoPhaseSolver.csproj", "{C0259681-7E14-4939-B525-310B3536D8CF}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SolverTest", "SolverTest\SolverTest.csproj", "{EA6D133F-B24E-42B6-826E-C18E6A6BDD61}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {C0259681-7E14-4939-B525-310B3536D8CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {C0259681-7E14-4939-B525-310B3536D8CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {C0259681-7E14-4939-B525-310B3536D8CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {C0259681-7E14-4939-B525-310B3536D8CF}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {EA6D133F-B24E-42B6-826E-C18E6A6BDD61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {EA6D133F-B24E-42B6-826E-C18E6A6BDD61}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {EA6D133F-B24E-42B6-826E-C18E6A6BDD61}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {EA6D133F-B24E-42B6-826E-C18E6A6BDD61}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | EndGlobal
29 |
--------------------------------------------------------------------------------
/TwoPhaseSolver/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("TwoPhaseSolver")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("TwoPhaseSolver")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("c0259681-7e14-4939-b525-310b3536d8cf")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TwoPhaseSolver
2 | Kociemba's algorithm implementation in C#.
3 |
4 | I originaly made it for a Mindstorms EV3 cube-solving robot, but it can be used in any situation. Note that I do not have any real experience in coding well, so the code is pretty much a mess without comments. I might add some documentation later on.
5 |
6 | # Building
7 | Simply open the solution in VisualStudio and hit "Build Solution". The "TwoPhaseSolver.dll" library and a test application named "SolverTest.exe" should be created.
8 |
9 | # Info
10 | Solves the rubik's cube using a two-phase algorithm. The code first maps different permuations of the cube as natural numbers. Then, it uses precomputed tables to apply moves to these numbers. The search is IDA*-like with four different prune tables as a heuristic. The code first tries to solve the cube in a position where all edges and corners have an orientation of 0 (phase 1), to then solve it as a whole (phase 2). Prune tables for phase 1 go up to depth 12 (they cover all of it) while phase 2 tables only cover depth 12 out of a maximum of 18. This means that the code will sometimes run very slow when asked to solve for a 20 or sometimes 21 move solution. It works great from 22 to 24 moves.
11 |
12 | # Notes
13 | The Search class is a C# port (with some modifications) of the one in Kociemba's Java implementation. All credit for this class goes to him. His website (http://kociemba.org/cube.htm) is the main source of information I used to program this two phase solver. I highly recommend checking it out if you want to know more about Rubik's cubes.
14 |
15 | Also note that the programs that generate the tables are NOT included in this solution. I might release them later.
16 |
--------------------------------------------------------------------------------
/TwoPhaseSolver/BinLoad.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.IO;
7 |
8 | namespace TwoPhaseSolver
9 | {
10 | static class BinLoad
11 | {
12 | public static byte[][] getUdToPerm(string path)
13 | {
14 | var raw = File.OpenRead(path);
15 | byte[][] values = new byte[Constants.N_UD][];
16 | byte[] c;
17 |
18 | for (var i = 0; i < Constants.N_UD; i++)
19 | {
20 | c = new byte[2];
21 | raw.Read(c, 0, 2);
22 |
23 | values[i] = new byte[4]
24 | {
25 | (byte)((c[0] & 0xf0) >> 4),
26 | (byte)(c[0] & 0x0f),
27 | (byte)((c[1] & 0xf0) >> 4),
28 | (byte)(c[1] & 0x0f)
29 | };
30 | }
31 |
32 | raw.Close();
33 | return values;
34 | }
35 |
36 | public static ushort[,] loadShortTable2D(string path, int chunksize = 18)
37 | {
38 | var bytes = File.ReadAllBytes(path);
39 | int len1d = bytes.Length / chunksize / 2;
40 | ushort[,] values = new ushort[len1d, chunksize];
41 | int i, j;
42 |
43 | for (i = 0; i < len1d; i++)
44 | {
45 | for (j = 0; j < chunksize; j++)
46 | {
47 | values[i, j] = (ushort)(
48 | (bytes[(chunksize * i + j) * 2] << 8) +
49 | bytes[(chunksize * i + j) * 2 + 1]
50 | );
51 | }
52 | }
53 |
54 | return values;
55 | }
56 |
57 | public static PruneTable loadPruneTable(string path)
58 | {
59 | return new PruneTable(File.ReadAllBytes(path));
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/TwoPhaseSolver/TwoPhaseSolver.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {C0259681-7E14-4939-B525-310B3536D8CF}
8 | Library
9 | Properties
10 | TwoPhaseSolver
11 | TwoPhaseSolver
12 | v4.5.2
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | mkdir "$(TargetDir)\tables"
56 | XCOPY "$(ProjectDir)tables" "$(TargetDir)\tables" /s /y
57 |
58 |
65 |
--------------------------------------------------------------------------------
/SolverTest/SolverTest.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {EA6D133F-B24E-42B6-826E-C18E6A6BDD61}
8 | Exe
9 | Properties
10 | SolverTest
11 | SolverTest
12 | v4.5.2
13 | 512
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | ..\TwoPhaseSolver\bin\Debug\TwoPhaseSolver.dll
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | mkdir "$(TargetDir)tables"
58 | XCOPY "$(SolutionDir)TwoPhaseSolver\tables" "$(TargetDir)tables" /y /s
59 |
60 |
67 |
--------------------------------------------------------------------------------
/TwoPhaseSolver/Tools.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace TwoPhaseSolver
8 | {
9 | static class Tools
10 | {
11 | public static int factorial(int n)
12 | {
13 | int k = 1;
14 | for (int i = 2; i < n; i++)
15 | {
16 | k *= i;
17 | }
18 | return k * n;
19 | }
20 |
21 | public static int nChooseK(int n, int k)
22 | {
23 | int i, j, s;
24 | if (n < k)
25 | return 0;
26 | if (k > n / 2)
27 | k = n - k;
28 | for (s = 1, i = n, j = 1; i != n - k; i--, j++)
29 | {
30 | s *= i;
31 | s /= j;
32 | }
33 | return s;
34 | }
35 |
36 | public static T[] rotate(this IEnumerable me, int amount)
37 | {
38 | var newarr = new T[me.Count()];
39 | int i = 0;
40 |
41 | foreach (T item in me)
42 | {
43 | newarr[(i + amount) % me.Count()] = item;
44 | i++;
45 | }
46 |
47 | return newarr;
48 | }
49 |
50 | public static int Index(this T[] me, T value, IEqualityComparer comparer)
51 | {
52 | for (int i = 0; i < me.Length; i++)
53 | {
54 | if (comparer.Equals(value, me[i])) { return i; }
55 | }
56 |
57 | return -1;
58 | }
59 |
60 | public static int Index(this T[] me, T value, Func comparer)
61 | {
62 | for (int i = 0; i < me.Length; i++)
63 | {
64 | if (comparer(value, me[i])) { return i; }
65 | }
66 |
67 | return -1;
68 | }
69 |
70 | public static int Index(this T[] me, T value) where T : IEquatable
71 | {
72 | for (int i = 0; i < me.Length; i++)
73 | {
74 | if (value.Equals(me[i])) { return i; }
75 | }
76 |
77 | return -1;
78 | }
79 |
80 | public static bool setEquals(this T[] a, T[] b)
81 | {
82 | var min = (a.Length >= b.Length) ? b : a;
83 | var max = (a.Length >= b.Length) ? a : b;
84 |
85 | foreach (T item in max)
86 | {
87 | if (!min.Contains(item)) { return false; }
88 | }
89 |
90 | return true;
91 | }
92 |
93 | static void ColorProcedure(object obj, Action