├── Arduino └── NULL ├── LICENSE ├── README.md ├── kociemba ├── color.h ├── coordcube.cpp ├── coordcube.h ├── corner.h ├── cubiecube.cpp ├── cubiecube.h ├── edge.h ├── facecube.cpp ├── facecube.h ├── facelet.h ├── prunetable_helpers.cpp ├── prunetable_helpers.h ├── search.cpp ├── search.h ├── solve.cpp └── umm └── vision ├── mend.cpp ├── mend.h ├── vision.cpp ├── vision.h └── 源.cpp /Arduino/NULL: -------------------------------------------------------------------------------- 1 | /. 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published 637 | by the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . 662 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cubesolver 2 | 这个项目提供一个魔方从视觉识别到求解过程再到通过串口发送给单片机的方案。 3 | *** 4 | 大二下学期(2018.5)做的魔方机器人,说要开源一直鸽到大四(2019.9)。不过终于有空了,稍微整理了一下放上来了。其实最难的部分还是需要一个精密的机械结构。此外代码全部是在Windows系统下用C++写的,视觉部分用到了opencv库。其他就没有别的依赖库了。 5 | 6 | 如果你使用代码时有任何疑问欢迎与我沟通~ 一起促进项目的发展! 此外该项目遵循GPLv3.0协议,使用时需要注意下。 7 | 8 | [视频点击这里](https://www.bilibili.com/video/av39119098?share_medium=android&share_source=copy_link&bbid=062C94C7-71EB-4C64-B933-F3DBE0F89912101704infoc&ts=1545876742959) 9 | *** 10 | ## 2019/9/16 小贺又回来了,决定继续写完代码了! 11 | 12 | 13 | ## 求解算法部分 14 | 15 | 开发环境是win10+VS2017 16 | 17 | 我使用的是kociemba算法 这个算法可以算出一个在21步左右的稳定的解。具体原理请参考[该链接](http://kociemba.org/download.htm) 18 | 19 | GitHub上有cs大佬写的min2phase写的双臂的二阶段算法 十分强!编程能力厉害一点的同学可以去搜搜 20 | 21 | Tip.在使用的时候需要注意自己电脑的系统和编译器的版本。 22 | 23 | ## 视觉算法: 24 | 25 | 开发环境是win10+VS2017 opencv3.4 is also required 26 | 27 | 1. 调用两个摄像头分别读取三个面 28 | 2. 图像预处理 直方图均衡化 模糊 29 | 3. 手动分割并提取RGBHSV六个值的平均值 这样三个面会有 27*6个值 30 | 31 | 4. 调用opencv ml库里面的SVM 预测值并返回(需要提前训练好模型) 32 | 5. 对收集的颜色进行三次检测 分别是总颜色 每个单独的颜色 以及魔方色块 33 | 6. 输出收集的颜色 34 | 35 | 36 | 37 | ## 单片机部分 38 | 39 | 使用的是Arduno mega2560 使用C++开发 总之很简单 40 | 41 | 重复使用的部分最好写成函数!不然代码看起十分ugly 42 | -------------------------------------------------------------------------------- /kociemba/color.h: -------------------------------------------------------------------------------- 1 | #ifndef COLOR_H 2 | #define COLOR_H 3 | // Names the colors of the cube facelets 4 | typedef enum {U, R, F, D, L, B} color_t; 5 | 6 | #define COLOR_COUNT 6 7 | #endif 8 | -------------------------------------------------------------------------------- /kociemba/coordcube.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "prunetable_helpers.h" 4 | #include "coordcube.h" 5 | #include "cubiecube.h" 6 | 7 | short twistMove[N_TWIST][N_MOVE]; 8 | short flipMove[N_FLIP][N_MOVE]; 9 | short parityMove[2][18] = { 10 | { 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1 }, 11 | { 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 } 12 | }; 13 | short FRtoBR_Move[N_FRtoBR][N_MOVE]; 14 | short URFtoDLF_Move[N_URFtoDLF][N_MOVE] = {{0}}; 15 | short URtoDF_Move[N_URtoDF][N_MOVE] = {{0}}; 16 | short URtoUL_Move[N_URtoUL][N_MOVE] = {{0}}; 17 | short UBtoDF_Move[N_UBtoDF][N_MOVE] = {{0}}; 18 | short MergeURtoULandUBtoDF[336][336] = {{0}}; 19 | signed char Slice_URFtoDLF_Parity_Prun[N_SLICE2 * N_URFtoDLF * N_PARITY / 2] = {0}; 20 | signed char Slice_URtoDF_Parity_Prun[N_SLICE2 * N_URtoDF * N_PARITY / 2] = {0}; 21 | signed char Slice_Twist_Prun[N_SLICE1 * N_TWIST / 2 + 1] = {0}; 22 | signed char Slice_Flip_Prun[N_SLICE1 * N_FLIP / 2] = {0}; 23 | 24 | int PRUNING_INITED = 0; 25 | 26 | void move(coordcube_t* coordcube, int m, const char *cache_dir) 27 | { 28 | if (PRUNING_INITED == 0) { 29 | initPruning(cache_dir); 30 | } 31 | coordcube->twist = twistMove[coordcube->twist][m]; 32 | coordcube->flip = flipMove[coordcube->flip][m]; 33 | coordcube->parity = parityMove[coordcube->parity][m]; 34 | coordcube->FRtoBR = FRtoBR_Move[coordcube->FRtoBR][m]; 35 | coordcube->URFtoDLF = URFtoDLF_Move[coordcube->URFtoDLF][m]; 36 | coordcube->URtoUL = URtoUL_Move[coordcube->URtoUL][m]; 37 | coordcube->UBtoDF = UBtoDF_Move[coordcube->UBtoDF][m]; 38 | if (coordcube->URtoUL < 336 && coordcube->UBtoDF < 336)// updated only if UR,UF,UL,UB,DR,DF 39 | // are not in UD-slice 40 | coordcube->URtoDF = MergeURtoULandUBtoDF[coordcube->URtoUL][coordcube->UBtoDF]; 41 | } 42 | 43 | coordcube_t* get_coordcube(cubiecube_t* cubiecube) 44 | { 45 | coordcube_t* result = (coordcube_t *) calloc(1, sizeof(coordcube_t)); 46 | 47 | result->twist = getTwist(cubiecube); 48 | result->flip = getFlip(cubiecube); 49 | result->parity = cornerParity(cubiecube); 50 | result->FRtoBR = getFRtoBR(cubiecube); 51 | result->URFtoDLF = getURFtoDLF(cubiecube); 52 | result->URtoUL = getURtoUL(cubiecube); 53 | result->UBtoDF = getUBtoDF(cubiecube); 54 | result->URtoDF = getURtoDF(cubiecube);// only needed in phase2 55 | 56 | return result; 57 | } 58 | 59 | void initPruning(const char *cache_dir) 60 | { 61 | cubiecube_t* a; 62 | cubiecube_t* moveCube = get_moveCube(); 63 | 64 | if(check_cached_table("twistMove", (void*) twistMove, sizeof(twistMove), cache_dir) != 0) { 65 | short i; 66 | int k, j; 67 | a = get_cubiecube(); 68 | for (i = 0; i < N_TWIST; i++) { 69 | setTwist(a, i); 70 | for (j = 0; j < 6; j++) { 71 | for (k = 0; k < 3; k++) { 72 | cornerMultiply(a, &moveCube[j]); 73 | twistMove[i][3 * j + k] = getTwist(a); 74 | } 75 | cornerMultiply(a, &moveCube[j]);// 4. faceturn restores 76 | } 77 | } 78 | free(a); 79 | dump_to_file((void*) twistMove, sizeof(twistMove), "twistMove", cache_dir); 80 | } 81 | 82 | if(check_cached_table("flipMove", (void*) flipMove, sizeof(flipMove), cache_dir) != 0) { 83 | short i; 84 | int k, j; 85 | a = get_cubiecube(); 86 | for (i = 0; i < N_FLIP; i++) { 87 | setFlip(a, i); 88 | for (j = 0; j < 6; j++) { 89 | for (k = 0; k < 3; k++) { 90 | edgeMultiply(a, &moveCube[j]); 91 | flipMove[i][3 * j + k] = getFlip(a); 92 | } 93 | edgeMultiply(a, &moveCube[j]); 94 | } 95 | } 96 | free(a); 97 | dump_to_file((void*) flipMove, sizeof(flipMove), "flipMove", cache_dir); 98 | } 99 | 100 | if(check_cached_table("FRtoBR_Move", (void*) FRtoBR_Move, sizeof(FRtoBR_Move), cache_dir) != 0) { 101 | short i; 102 | int k, j; 103 | a = get_cubiecube(); 104 | for (i = 0; i < N_FRtoBR; i++) { 105 | setFRtoBR(a, i); 106 | for (j = 0; j < 6; j++) { 107 | for (k = 0; k < 3; k++) { 108 | edgeMultiply(a, &moveCube[j]); 109 | FRtoBR_Move[i][3 * j + k] = getFRtoBR(a); 110 | } 111 | edgeMultiply(a, &moveCube[j]); 112 | } 113 | } 114 | free(a); 115 | dump_to_file((void*) FRtoBR_Move, sizeof(FRtoBR_Move), "FRtoBR_Move", cache_dir); 116 | } 117 | 118 | if(check_cached_table("URFtoDLF_Move", (void*) URFtoDLF_Move, sizeof(URFtoDLF_Move), cache_dir) != 0) { 119 | short i; 120 | int k, j; 121 | a = get_cubiecube(); 122 | for (i = 0; i < N_URFtoDLF; i++) { 123 | setURFtoDLF(a, i); 124 | for (j = 0; j < 6; j++) { 125 | for (k = 0; k < 3; k++) { 126 | cornerMultiply(a, &moveCube[j]); 127 | URFtoDLF_Move[i][3 * j + k] = getURFtoDLF(a); 128 | } 129 | cornerMultiply(a, &moveCube[j]); 130 | } 131 | } 132 | free(a); 133 | dump_to_file((void*) URFtoDLF_Move, sizeof(URFtoDLF_Move), "URFtoDLF_Move", cache_dir); 134 | } 135 | 136 | if(check_cached_table("URtoDF_Move", (void*) URtoDF_Move, sizeof(URtoDF_Move), cache_dir) != 0) { 137 | short i; 138 | int k, j; 139 | a = get_cubiecube(); 140 | for (i = 0; i < N_URtoDF; i++) { 141 | setURtoDF(a, i); 142 | for (j = 0; j < 6; j++) { 143 | for (k = 0; k < 3; k++) { 144 | edgeMultiply(a, &moveCube[j]); 145 | URtoDF_Move[i][3 * j + k] = (short) getURtoDF(a); 146 | // Table values are only valid for phase 2 moves! 147 | // For phase 1 moves, casting to short is not possible. 148 | } 149 | edgeMultiply(a, &moveCube[j]); 150 | } 151 | } 152 | free(a); 153 | dump_to_file((void*) URtoDF_Move, sizeof(URtoDF_Move), "URtoDF_Move", cache_dir); 154 | } 155 | 156 | if(check_cached_table("URtoUL_Move", (void*) URtoUL_Move, sizeof(URtoUL_Move), cache_dir) != 0) { 157 | short i; 158 | int k, j; 159 | a = get_cubiecube(); 160 | for (i = 0; i < N_URtoUL; i++) { 161 | setURtoUL(a, i); 162 | for (j = 0; j < 6; j++) { 163 | for (k = 0; k < 3; k++) { 164 | edgeMultiply(a, &moveCube[j]); 165 | URtoUL_Move[i][3 * j + k] = getURtoUL(a); 166 | } 167 | edgeMultiply(a, &moveCube[j]); 168 | } 169 | } 170 | free(a); 171 | dump_to_file((void*) URtoUL_Move, sizeof(URtoUL_Move), "URtoUL_Move", cache_dir); 172 | } 173 | 174 | if(check_cached_table("UBtoDF_Move", (void*) UBtoDF_Move, sizeof(UBtoDF_Move), cache_dir) != 0) { 175 | short i; 176 | int k, j; 177 | a = get_cubiecube(); 178 | for (i = 0; i < N_UBtoDF; i++) { 179 | setUBtoDF(a, i); 180 | for (j = 0; j < 6; j++) { 181 | for (k = 0; k < 3; k++) { 182 | edgeMultiply(a, &moveCube[j]); 183 | UBtoDF_Move[i][3 * j + k] = getUBtoDF(a); 184 | } 185 | edgeMultiply(a, &moveCube[j]); 186 | } 187 | } 188 | free(a); 189 | dump_to_file((void*) UBtoDF_Move, sizeof(UBtoDF_Move), "UBtoDF_Move", cache_dir); 190 | } 191 | 192 | if(check_cached_table("MergeURtoULandUBtoDF", (void*) MergeURtoULandUBtoDF, sizeof(MergeURtoULandUBtoDF), cache_dir) != 0) { 193 | // for i, j <336 the six edges UR,UF,UL,UB,DR,DF are not in the 194 | // UD-slice and the index is <20160 195 | short uRtoUL, uBtoDF; 196 | for (uRtoUL = 0; uRtoUL < 336; uRtoUL++) { 197 | for (uBtoDF = 0; uBtoDF < 336; uBtoDF++) { 198 | MergeURtoULandUBtoDF[uRtoUL][uBtoDF] = (short) getURtoDF_standalone(uRtoUL, uBtoDF); 199 | } 200 | } 201 | dump_to_file((void*) MergeURtoULandUBtoDF, sizeof(MergeURtoULandUBtoDF), "MergeURtoULandUBtoDF", cache_dir); 202 | } 203 | 204 | if(check_cached_table("Slice_URFtoDLF_Parity_Prun", (void*) Slice_URFtoDLF_Parity_Prun, sizeof(Slice_URFtoDLF_Parity_Prun), cache_dir) != 0) { 205 | int depth = 0, done = 1; 206 | int i, j; 207 | for (i = 0; i < N_SLICE2 * N_URFtoDLF * N_PARITY / 2; i++) 208 | Slice_URFtoDLF_Parity_Prun[i] = -1; 209 | setPruning(Slice_URFtoDLF_Parity_Prun, 0, 0); 210 | printf("1\n"); 211 | while (done != N_SLICE2 * N_URFtoDLF * N_PARITY) { 212 | // printf("%d %d %d\n", done, N_SLICE2 * N_URFtoDLF * N_PARITY, depth); 213 | for (i = 0; i < N_SLICE2 * N_URFtoDLF * N_PARITY; i++) { 214 | int parity = i % 2; 215 | int URFtoDLF = (i / 2) / N_SLICE2; 216 | int slice = (i / 2) % N_SLICE2; 217 | if (getPruning(Slice_URFtoDLF_Parity_Prun, i) == depth) { 218 | for (j = 0; j < 18; j++) { 219 | int newSlice; 220 | int newURFtoDLF; 221 | int newParity; 222 | switch (j) { 223 | case 3: 224 | case 5: 225 | case 6: 226 | case 8: 227 | case 12: 228 | case 14: 229 | case 15: 230 | case 17: 231 | continue; 232 | default: 233 | newSlice = FRtoBR_Move[slice][j]; 234 | newURFtoDLF = URFtoDLF_Move[URFtoDLF][j]; 235 | newParity = parityMove[parity][j]; 236 | if (getPruning(Slice_URFtoDLF_Parity_Prun, (N_SLICE2 * newURFtoDLF + newSlice) * 2 + newParity) == 0x0f) { 237 | setPruning(Slice_URFtoDLF_Parity_Prun, (N_SLICE2 * newURFtoDLF + newSlice) * 2 + newParity, 238 | (signed char) (depth + 1)); 239 | done++; 240 | } 241 | } 242 | } 243 | } 244 | } 245 | depth++; 246 | } 247 | printf("2\n"); 248 | dump_to_file((void*) Slice_URFtoDLF_Parity_Prun, sizeof(Slice_URFtoDLF_Parity_Prun), "Slice_URFtoDLF_Parity_Prun", cache_dir); 249 | printf("3\n"); 250 | } 251 | 252 | if(check_cached_table("Slice_URtoDF_Parity_Prun", (void*) Slice_URtoDF_Parity_Prun, sizeof(Slice_URtoDF_Parity_Prun), cache_dir) != 0) { 253 | int depth = 0, done = 1; 254 | int i, j; 255 | for (i = 0; i < N_SLICE2 * N_URtoDF * N_PARITY / 2; i++) 256 | Slice_URtoDF_Parity_Prun[i] = -1; 257 | setPruning(Slice_URtoDF_Parity_Prun, 0, 0); 258 | while (done != N_SLICE2 * N_URtoDF * N_PARITY) { 259 | for (i = 0; i < N_SLICE2 * N_URtoDF * N_PARITY; i++) { 260 | int parity = i % 2; 261 | int URtoDF = (i / 2) / N_SLICE2; 262 | int slice = (i / 2) % N_SLICE2; 263 | if (getPruning(Slice_URtoDF_Parity_Prun, i) == depth) { 264 | for (j = 0; j < 18; j++) { 265 | int newSlice; 266 | int newURtoDF; 267 | int newParity; 268 | switch (j) { 269 | case 3: 270 | case 5: 271 | case 6: 272 | case 8: 273 | case 12: 274 | case 14: 275 | case 15: 276 | case 17: 277 | continue; 278 | default: 279 | newSlice = FRtoBR_Move[slice][j]; 280 | newURtoDF = URtoDF_Move[URtoDF][j]; 281 | newParity = parityMove[parity][j]; 282 | if (getPruning(Slice_URtoDF_Parity_Prun, (N_SLICE2 * newURtoDF + newSlice) * 2 + newParity) == 0x0f) { 283 | setPruning(Slice_URtoDF_Parity_Prun, (N_SLICE2 * newURtoDF + newSlice) * 2 + newParity, 284 | (signed char) (depth + 1)); 285 | done++; 286 | } 287 | } 288 | } 289 | } 290 | } 291 | depth++; 292 | } 293 | dump_to_file((void*) Slice_URtoDF_Parity_Prun, sizeof(Slice_URtoDF_Parity_Prun), "Slice_URtoDF_Parity_Prun", cache_dir); 294 | } 295 | 296 | if(check_cached_table("Slice_Twist_Prun", (void*) Slice_Twist_Prun, sizeof(Slice_Twist_Prun), cache_dir) != 0) { 297 | int depth = 0, done = 1; 298 | int i, j; 299 | for (i = 0; i < N_SLICE1 * N_TWIST / 2 + 1; i++) 300 | Slice_Twist_Prun[i] = -1; 301 | setPruning(Slice_Twist_Prun, 0, 0); 302 | while (done != N_SLICE1 * N_TWIST) { 303 | for (i = 0; i < N_SLICE1 * N_TWIST; i++) { 304 | int twist = i / N_SLICE1, slice = i % N_SLICE1; 305 | if (getPruning(Slice_Twist_Prun, i) == depth) { 306 | for (j = 0; j < 18; j++) { 307 | int newSlice = FRtoBR_Move[slice * 24][j] / 24; 308 | int newTwist = twistMove[twist][j]; 309 | if (getPruning(Slice_Twist_Prun, N_SLICE1 * newTwist + newSlice) == 0x0f) { 310 | setPruning(Slice_Twist_Prun, N_SLICE1 * newTwist + newSlice, (signed char) (depth + 1)); 311 | done++; 312 | } 313 | } 314 | } 315 | } 316 | depth++; 317 | } 318 | dump_to_file((void*) Slice_Twist_Prun, sizeof(Slice_Twist_Prun), "Slice_Twist_Prun", cache_dir); 319 | } 320 | 321 | if(check_cached_table("Slice_Flip_Prun", (void*) Slice_Flip_Prun, sizeof(Slice_Flip_Prun), cache_dir) != 0) { 322 | int depth = 0, done = 1; 323 | int i, j; 324 | for (i = 0; i < N_SLICE1 * N_FLIP / 2; i++) 325 | Slice_Flip_Prun[i] = -1; 326 | setPruning(Slice_Flip_Prun, 0, 0); 327 | while (done != N_SLICE1 * N_FLIP) { 328 | for (i = 0; i < N_SLICE1 * N_FLIP; i++) { 329 | int flip = i / N_SLICE1, slice = i % N_SLICE1; 330 | if (getPruning(Slice_Flip_Prun, i) == depth) { 331 | for (j = 0; j < 18; j++) { 332 | int newSlice = FRtoBR_Move[slice * 24][j] / 24; 333 | int newFlip = flipMove[flip][j]; 334 | if (getPruning(Slice_Flip_Prun, N_SLICE1 * newFlip + newSlice) == 0x0f) { 335 | setPruning(Slice_Flip_Prun, N_SLICE1 * newFlip + newSlice, (signed char) (depth + 1)); 336 | done++; 337 | } 338 | } 339 | } 340 | } 341 | depth++; 342 | } 343 | dump_to_file((void*) Slice_Flip_Prun, sizeof(Slice_Flip_Prun), "Slice_Flip_Prun", cache_dir); 344 | } 345 | 346 | PRUNING_INITED = 1; 347 | } 348 | 349 | void setPruning(signed char *table, int index, signed char value) { 350 | if ((index & 1) == 0) 351 | table[index / 2] &= 0xf0 | value; 352 | else 353 | table[index / 2] &= 0x0f | (value << 4); 354 | } 355 | 356 | // Extract pruning value 357 | signed char getPruning(signed char *table, int index) { 358 | signed char res; 359 | 360 | if ((index & 1) == 0) 361 | res = (table[index / 2] & 0x0f); 362 | else 363 | res = ((table[index / 2] >> 4) & 0x0f); 364 | 365 | return res; 366 | } 367 | -------------------------------------------------------------------------------- /kociemba/coordcube.h: -------------------------------------------------------------------------------- 1 | #ifndef COORDCUBE_H 2 | #define COORDCUBE_H 3 | 4 | #include "cubiecube.h" 5 | 6 | // Representation of the cube on the coordinate level 7 | 8 | #define N_TWIST 2187 9 | #define N_FLIP 2048 10 | #define N_SLICE1 495 11 | #define N_SLICE2 24 12 | #define N_PARITY 2 13 | #define N_URFtoDLF 20160 14 | #define N_FRtoBR 11880 15 | #define N_URtoUL 1320 16 | #define N_UBtoDF 1320 17 | #define N_URtoDF 20160 18 | #define N_URFtoDLB 40320 19 | #define N_URtoBR 479001600 20 | #define N_MOVE 18 21 | 22 | typedef struct { 23 | 24 | // All coordinates are 0 for a solved cube except for UBtoDF, which is 114 25 | short twist; 26 | short flip; 27 | short parity; 28 | short FRtoBR; 29 | short URFtoDLF; 30 | short URtoUL; 31 | short UBtoDF; 32 | int URtoDF; 33 | } coordcube_t; 34 | 35 | // ******************************************Phase 1 move tables***************************************************** 36 | 37 | // Move table for the twists of the corners 38 | // twist < 2187 in phase 2. 39 | // twist = 0 in phase 2. 40 | extern short twistMove[N_TWIST][N_MOVE]; 41 | 42 | // Move table for the flips of the edges 43 | // flip < 2048 in phase 1 44 | // flip = 0 in phase 2. 45 | extern short flipMove[N_FLIP][N_MOVE]; 46 | 47 | // Parity of the corner permutation. This is the same as the parity for the edge permutation of a valid cube. 48 | // parity has values 0 and 1 49 | extern short parityMove[2][18]; 50 | 51 | // ***********************************Phase 1 and 2 movetable******************************************************** 52 | 53 | // Move table for the four UD-slice edges FR, FL, Bl and BR 54 | // FRtoBRMove < 11880 in phase 1 55 | // FRtoBRMove < 24 in phase 2 56 | // FRtoBRMove = 0 for solved cube 57 | extern short FRtoBR_Move[N_FRtoBR][N_MOVE]; 58 | 59 | // Move table for permutation of six corners. The positions of the DBL and DRB corners are determined by the parity. 60 | // URFtoDLF < 20160 in phase 1 61 | // URFtoDLF < 20160 in phase 2 62 | // URFtoDLF = 0 for solved cube. 63 | extern short URFtoDLF_Move[N_URFtoDLF][N_MOVE]; 64 | 65 | // Move table for the permutation of six U-face and D-face edges in phase2. The positions of the DL and DB edges are 66 | // determined by the parity. 67 | // URtoDF < 665280 in phase 1 68 | // URtoDF < 20160 in phase 2 69 | // URtoDF = 0 for solved cube. 70 | extern short URtoDF_Move[N_URtoDF][N_MOVE]; 71 | 72 | // **************************helper move tables to compute URtoDF for the beginning of phase2************************ 73 | 74 | // Move table for the three edges UR,UF and UL in phase1. 75 | extern short URtoUL_Move[N_URtoUL][N_MOVE]; 76 | 77 | // Move table for the three edges UB,DR and DF in phase1. 78 | extern short UBtoDF_Move[N_UBtoDF][N_MOVE]; 79 | 80 | // Table to merge the coordinates of the UR,UF,UL and UB,DR,DF edges at the beginning of phase2 81 | extern short MergeURtoULandUBtoDF[336][336]; 82 | 83 | // ****************************************Pruning tables for the search********************************************* 84 | 85 | // Pruning table for the permutation of the corners and the UD-slice edges in phase2. 86 | // The pruning table entries give a lower estimation for the number of moves to reach the solved cube. 87 | extern signed char Slice_URFtoDLF_Parity_Prun[N_SLICE2 * N_URFtoDLF * N_PARITY / 2]; 88 | 89 | // Pruning table for the permutation of the edges in phase2. 90 | // The pruning table entries give a lower estimation for the number of moves to reach the solved cube. 91 | extern signed char Slice_URtoDF_Parity_Prun[N_SLICE2 * N_URtoDF * N_PARITY / 2]; 92 | 93 | // Pruning table for the twist of the corners and the position (not permutation) of the UD-slice edges in phase1 94 | // The pruning table entries give a lower estimation for the number of moves to reach the H-subgroup. 95 | extern signed char Slice_Twist_Prun[N_SLICE1 * N_TWIST / 2 + 1]; 96 | 97 | // Pruning table for the flip of the edges and the position (not permutation) of the UD-slice edges in phase1 98 | // The pruning table entries give a lower estimation for the number of moves to reach the H-subgroup. 99 | extern signed char Slice_Flip_Prun[N_SLICE1 * N_FLIP / 2]; 100 | 101 | extern int PRUNING_INITED; 102 | void initPruning(const char *cache_dir); 103 | 104 | // Set pruning value in table. Two values are stored in one char. 105 | void setPruning(signed char *table, int index, signed char value); 106 | 107 | // Extract pruning value 108 | signed char getPruning(signed char *table, int index); 109 | 110 | coordcube_t* get_coordcube(cubiecube_t* cubiecube); 111 | void move(coordcube_t* coordcube, int m, const char *cache_dir); 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /kociemba/corner.h: -------------------------------------------------------------------------------- 1 | #ifndef CORNER_H 2 | #define CORNER_H 3 | // The names of the corner positions of the cube. Corner URF e.g., has an U(p), a R(ight) and a F(ront) facelet 4 | typedef enum { 5 | URF, UFL, ULB, UBR, DFR, DLF, DBL, DRB 6 | } corner_t; 7 | 8 | #define CORNER_COUNT 8 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /kociemba/cubiecube.cpp: -------------------------------------------------------------------------------- 1 | #include "cubiecube.h" 2 | #include "facecube.h" 3 | 4 | cubiecube_t * get_moveCube() 5 | { 6 | static cubiecube_t moveCube[6]; 7 | static int moveCube_initialized = 0; 8 | static const corner_t cpU[8] = { UBR, URF, UFL, ULB, DFR, DLF, DBL, DRB }; 9 | static const signed char coU[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 10 | static const edge_t epU[12] = { UB, UR, UF, UL, DR, DF, DL, DB, FR, FL, BL, BR }; 11 | static const signed char eoU[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 12 | static const corner_t cpR[8] = { DFR, UFL, ULB, URF, DRB, DLF, DBL, UBR }; 13 | static const signed char coR[8] = { 2, 0, 0, 1, 1, 0, 0, 2 }; 14 | static const edge_t epR[12] = { FR, UF, UL, UB, BR, DF, DL, DB, DR, FL, BL, UR }; 15 | static const signed char eoR[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 16 | static const corner_t cpF[8] = { UFL, DLF, ULB, UBR, URF, DFR, DBL, DRB }; 17 | static const signed char coF[8] = { 1, 2, 0, 0, 2, 1, 0, 0 }; 18 | static const edge_t epF[12] = { UR, FL, UL, UB, DR, FR, DL, DB, UF, DF, BL, BR }; 19 | static const signed char eoF[12] = { 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0 }; 20 | static const corner_t cpD[8] = { URF, UFL, ULB, UBR, DLF, DBL, DRB, DFR }; 21 | static const signed char coD[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 22 | static const edge_t epD[12] = { UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR }; 23 | static const signed char eoD[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 24 | static const corner_t cpL[8] = { URF, ULB, DBL, UBR, DFR, UFL, DLF, DRB }; 25 | static const signed char coL[8] = { 0, 1, 2, 0, 0, 2, 1, 0 }; 26 | static const edge_t epL[12] = { UR, UF, BL, UB, DR, DF, FL, DB, FR, UL, DL, BR }; 27 | static const signed char eoL[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 28 | static const corner_t cpB[8] = { URF, UFL, UBR, DRB, DFR, DLF, ULB, DBL }; 29 | static const signed char coB[8] = { 0, 0, 1, 2, 0, 0, 2, 1 }; 30 | static const edge_t epB[12] = { UR, UF, UL, BR, DR, DF, DL, BL, FR, FL, UB, DB }; 31 | static const signed char eoB[12] = { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1 }; 32 | 33 | if (!moveCube_initialized) { 34 | memcpy(moveCube[0].cp, cpU, sizeof(cpU)); 35 | memcpy(moveCube[0].co, coU, sizeof(coU)); 36 | memcpy(moveCube[0].ep, epU, sizeof(epU)); 37 | memcpy(moveCube[0].eo, eoU, sizeof(eoU)); 38 | memcpy(moveCube[1].cp, cpR, sizeof(cpR)); 39 | memcpy(moveCube[1].co, coR, sizeof(coR)); 40 | memcpy(moveCube[1].ep, epR, sizeof(epR)); 41 | memcpy(moveCube[1].eo, eoR, sizeof(eoR)); 42 | memcpy(moveCube[2].cp, cpF, sizeof(cpF)); 43 | memcpy(moveCube[2].co, coF, sizeof(coF)); 44 | memcpy(moveCube[2].ep, epF, sizeof(epF)); 45 | memcpy(moveCube[2].eo, eoF, sizeof(eoF)); 46 | memcpy(moveCube[3].cp, cpD, sizeof(cpD)); 47 | memcpy(moveCube[3].co, coD, sizeof(coD)); 48 | memcpy(moveCube[3].ep, epD, sizeof(epD)); 49 | memcpy(moveCube[3].eo, eoD, sizeof(eoD)); 50 | memcpy(moveCube[4].cp, cpL, sizeof(cpL)); 51 | memcpy(moveCube[4].co, coL, sizeof(coL)); 52 | memcpy(moveCube[4].ep, epL, sizeof(epL)); 53 | memcpy(moveCube[4].eo, eoL, sizeof(eoL)); 54 | memcpy(moveCube[5].cp, cpB, sizeof(cpB)); 55 | memcpy(moveCube[5].co, coB, sizeof(coB)); 56 | memcpy(moveCube[5].ep, epB, sizeof(epB)); 57 | memcpy(moveCube[5].eo, eoB, sizeof(eoB)); 58 | } 59 | 60 | return moveCube; 61 | } 62 | 63 | cubiecube_t* get_cubiecube() 64 | { 65 | cubiecube_t* result = (cubiecube_t *) calloc(1, sizeof(cubiecube_t)); 66 | 67 | static const corner_t cp[8] = { URF, UFL, ULB, UBR, DFR, DLF, DBL, DRB }; 68 | static const signed char co[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 69 | static const edge_t ep[12] = { UR, UF, UL, UB, DR, DF, DL, DB, FR, FL, BL, BR }; 70 | static const signed char eo[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 71 | 72 | memcpy(result->cp, cp, sizeof(cp)); 73 | memcpy(result->co, co, sizeof(co)); 74 | memcpy(result->ep, ep, sizeof(ep)); 75 | memcpy(result->eo, eo, sizeof(eo)); 76 | 77 | return result; 78 | } 79 | 80 | int Cnk(int n, int k) { 81 | int i, j, s; 82 | if (n < k) 83 | return 0; 84 | if (k > n / 2) 85 | k = n - k; 86 | for (s = 1, i = n, j = 1; i != n - k; i--, j++) { 87 | s *= i; 88 | s /= j; 89 | } 90 | return s; 91 | } 92 | 93 | void rotateLeft_corner(corner_t* arr, int l, int r) 94 | // Left rotation of all array elements between l and r 95 | { 96 | int i; 97 | corner_t temp = arr[l]; 98 | for (i = l; i < r; i++) 99 | arr[i] = arr[i + 1]; 100 | arr[r] = temp; 101 | } 102 | 103 | void rotateRight_corner(corner_t* arr, int l, int r) 104 | // Right rotation of all array elements between l and r 105 | { 106 | int i; 107 | corner_t temp = arr[r]; 108 | for (i = r; i > l; i--) 109 | arr[i] = arr[i - 1]; 110 | arr[l] = temp; 111 | } 112 | 113 | 114 | void rotateLeft_edge(edge_t* arr, int l, int r) 115 | // Left rotation of all array elements between l and r 116 | { 117 | int i; 118 | edge_t temp = arr[l]; 119 | for (i = l; i < r; i++) 120 | arr[i] = arr[i + 1]; 121 | arr[r] = temp; 122 | } 123 | 124 | void rotateRight_edge(edge_t* arr, int l, int r) 125 | // Right rotation of all array elements between l and r 126 | { 127 | int i; 128 | edge_t temp = arr[r]; 129 | for (i = r; i > l; i--) 130 | arr[i] = arr[i - 1]; 131 | arr[l] = temp; 132 | } 133 | 134 | facecube_t* toFaceCube(cubiecube_t* cubiecube) 135 | { 136 | int i, j, n; 137 | signed char ori; 138 | facecube_t* fcRet = get_facecube(); 139 | for(i = 0; i < CORNER_COUNT; i++) { 140 | j = cubiecube->cp[i];// cornercubie with index j is at 141 | // cornerposition with index i 142 | ori = cubiecube->co[i];// Orientation of this cubie 143 | for (n = 0; n < 3; n++) 144 | fcRet->f[cornerFacelet[i][(n + ori) % 3]] = cornerColor[j][n]; 145 | } 146 | for(i = 0; i < EDGE_COUNT; i++) 147 | { 148 | j = cubiecube->ep[i];// edgecubie with index j is at edgeposition 149 | // with index i 150 | ori = cubiecube->eo[i];// Orientation of this cubie 151 | for (n = 0; n < 2; n++) 152 | fcRet->f[edgeFacelet[i][(n + ori) % 2]] = edgeColor[j][n]; 153 | } 154 | return fcRet; 155 | } 156 | 157 | void cornerMultiply(cubiecube_t* cubiecube, cubiecube_t* b) 158 | { 159 | int corn; 160 | signed char oriA, oriB, ori; 161 | corner_t cPerm[8] = { corner_t(0)}; 162 | signed char cOri[8] = {0}; 163 | for (corn = 0; corn < CORNER_COUNT; corn++) { 164 | cPerm[corn] = cubiecube->cp[b->cp[corn]]; 165 | 166 | oriA = cubiecube->co[b->cp[corn]]; 167 | oriB = b->co[corn]; 168 | ori = 0; 169 | 170 | if (oriA < 3 && oriB < 3) // if both cubes are regular cubes... 171 | { 172 | ori = oriA + oriB; // just do an addition modulo 3 here 173 | if (ori >= 3) 174 | ori -= 3; // the composition is a regular cube 175 | 176 | // +++++++++++++++++++++not used in this implementation +++++++++++++++++++++++++++++++++++ 177 | } else if (oriA < 3 && oriB >= 3) // if cube b is in a mirrored 178 | // state... 179 | { 180 | ori = oriA + oriB; 181 | if (ori >= 6) 182 | ori -= 3; // the composition is a mirrored cube 183 | } else if (oriA >= 3 && oriB < 3) // if cube a is an a mirrored 184 | // state... 185 | { 186 | ori = oriA - oriB; 187 | if (ori < 3) 188 | ori += 3; // the composition is a mirrored cube 189 | } else if (oriA >= 3 && oriB >= 3) // if both cubes are in mirrored 190 | // states... 191 | { 192 | ori = oriA - oriB; 193 | if (ori < 0) 194 | ori += 3; // the composition is a regular cube 195 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 196 | } 197 | cOri[corn] = ori; 198 | } 199 | for(corn = 0; corn < CORNER_COUNT; corn++) { 200 | cubiecube->cp[corn] = cPerm[corn]; 201 | cubiecube->co[corn] = cOri[corn]; 202 | } 203 | } 204 | 205 | void edgeMultiply(cubiecube_t* cubiecube, cubiecube_t* b) 206 | { 207 | int edge; 208 | edge_t ePerm[12] = { edge_t(0)}; 209 | signed char eOri[12] = {0}; 210 | 211 | for(edge = 0; edge < EDGE_COUNT; edge++) { 212 | ePerm[edge] = cubiecube->ep[b->ep[edge]]; 213 | eOri[edge] = (b->eo[edge] + cubiecube->eo[b->ep[edge]]) % 2; 214 | } 215 | for(edge = 0; edge < EDGE_COUNT; edge++) { 216 | cubiecube->ep[edge] = ePerm[edge]; 217 | cubiecube->eo[edge] = eOri[edge]; 218 | } 219 | } 220 | 221 | void multiply(cubiecube_t* cubiecube, cubiecube_t* b) 222 | { 223 | cornerMultiply(cubiecube, b); 224 | edgeMultiply(cubiecube, b); 225 | } 226 | 227 | void invCubieCube(cubiecube_t* cubiecube, cubiecube_t* c) 228 | { 229 | int edge, corn; 230 | for (edge = 0; edge < EDGE_COUNT; edge++) 231 | c->ep[cubiecube->ep[edge]] = edge_t(edge); 232 | for (edge = 0; edge < EDGE_COUNT; edge++) 233 | c->eo[edge] = cubiecube->eo[c->ep[edge]]; 234 | for (corn = 0; corn < CORNER_COUNT; corn++) 235 | c->cp[cubiecube->cp[corn]] = corner_t(corn); 236 | for (corn = 0; corn < CORNER_COUNT; corn++) { 237 | signed char ori = cubiecube->co[c->cp[corn]]; 238 | if (ori >= 3)// Just for completeness. We do not invert mirrored 239 | // cubes in the program. 240 | c->co[corn] = ori; 241 | else {// the standard case 242 | c->co[corn] = -ori; 243 | if (c->co[corn] < 0) 244 | c->co[corn] += 3; 245 | } 246 | } 247 | } 248 | 249 | short getTwist(cubiecube_t* cubiecube) 250 | { 251 | short ret = 0; 252 | int i; 253 | for (i = URF; i < DRB; i++) 254 | ret = (short) (3 * ret + cubiecube->co[i]); 255 | return ret; 256 | } 257 | 258 | void setTwist(cubiecube_t* cubiecube, short twist) 259 | { 260 | int twistParity = 0; 261 | int i; 262 | for (i = DRB - 1; i >= URF; i--) { 263 | twistParity += cubiecube->co[i] = (signed char) (twist % 3); 264 | twist /= 3; 265 | } 266 | cubiecube->co[DRB] = (signed char) ((3 - twistParity % 3) % 3); 267 | } 268 | 269 | short getFlip(cubiecube_t* cubiecube) 270 | { 271 | int i; 272 | short ret = 0; 273 | for (i = UR; i < BR; i++) 274 | ret = (short) (2 * ret + cubiecube->eo[i]); 275 | return ret; 276 | } 277 | 278 | void setFlip(cubiecube_t* cubiecube, short flip) 279 | { 280 | int i; 281 | int flipParity = 0; 282 | for (i = BR - 1; i >= UR; i--) { 283 | flipParity += cubiecube->eo[i] = (signed char) (flip % 2); 284 | flip /= 2; 285 | } 286 | cubiecube->eo[BR] = (signed char) ((2 - flipParity % 2) % 2); 287 | } 288 | 289 | short cornerParity(cubiecube_t* cubiecube) 290 | { 291 | int i, j; 292 | int s = 0; 293 | for (i = DRB; i >= URF + 1; i--) 294 | for (j = i - 1; j >= URF; j--) 295 | if (cubiecube->cp[j] > cubiecube->cp[i]) 296 | s++; 297 | return (short) (s % 2); 298 | } 299 | 300 | short edgeParity(cubiecube_t* cubiecube) 301 | { 302 | int i, j; 303 | int s = 0; 304 | for (i = BR; i >= UR + 1; i--) 305 | for (j = i - 1; j >= UR; j--) 306 | if (cubiecube->ep[j] > cubiecube->ep[i]) 307 | s++; 308 | return (short) (s % 2); 309 | } 310 | 311 | short getFRtoBR(cubiecube_t* cubiecube) 312 | { 313 | int a = 0, x = 0, j; 314 | int b = 0; 315 | edge_t edge4[4] = { edge_t(0)}; 316 | // compute the index a < (12 choose 4) and the permutation array perm. 317 | for (j = BR; j >= UR; j--) 318 | if (FR <= cubiecube->ep[j] && cubiecube->ep[j] <= BR) { 319 | a += Cnk(11 - j, x + 1); 320 | edge4[3 - x++] = cubiecube->ep[j]; 321 | } 322 | 323 | for (j = 3; j > 0; j--)// compute the index b < 4! for the 324 | // permutation in perm 325 | { 326 | int k = 0; 327 | while (edge4[j] != j + 8) { 328 | rotateLeft_edge(edge4, 0, j); 329 | k++; 330 | } 331 | b = (j + 1) * b + k; 332 | } 333 | return (short) (24 * a + b); 334 | } 335 | void setFRtoBR(cubiecube_t* cubiecube, short idx) 336 | { 337 | int x, j, k, e; 338 | edge_t sliceEdge[4] = { FR, FL, BL, BR }; 339 | edge_t otherEdge[8] = { UR, UF, UL, UB, DR, DF, DL, DB }; 340 | int b = idx % 24; // Permutation 341 | int a = idx / 24; // Combination 342 | for (e = 0; e < EDGE_COUNT; e++) 343 | cubiecube->ep[e] = DB;// Use UR to invalidate all edges 344 | 345 | for (j = 1; j < 4; j++)// generate permutation from index b 346 | { 347 | k = b % (j + 1); 348 | b /= j + 1; 349 | while (k-- > 0) 350 | rotateRight_edge(sliceEdge, 0, j); 351 | } 352 | 353 | x = 3;// generate combination and set slice edges 354 | for (j = UR; j <= BR; j++) 355 | if (a - Cnk(11 - j, x + 1) >= 0) { 356 | cubiecube->ep[j] = sliceEdge[3 - x]; 357 | a -= Cnk(11 - j, x-- + 1); 358 | } 359 | x = 0; // set the remaining edges UR..DB 360 | for (j = UR; j <= BR; j++) 361 | if (cubiecube->ep[j] == DB) 362 | cubiecube->ep[j] = otherEdge[x++]; 363 | } 364 | 365 | short getURFtoDLF(cubiecube_t* cubiecube) 366 | { 367 | int a = 0, x = 0, j, b = 0; 368 | corner_t corner6[6] = { corner_t(0)}; 369 | // compute the index a < (8 choose 6) and the corner permutation. 370 | for (j = URF; j <= DRB; j++) 371 | if (cubiecube->cp[j] <= DLF) { 372 | a += Cnk(j, x + 1); 373 | corner6[x++] = cubiecube->cp[j]; 374 | } 375 | 376 | for (j = 5; j > 0; j--)// compute the index b < 6! for the 377 | // permutation in corner6 378 | { 379 | int k = 0; 380 | while (corner6[j] != j) { 381 | rotateLeft_corner(corner6, 0, j); 382 | k++; 383 | } 384 | b = (j + 1) * b + k; 385 | } 386 | return (short) (720 * a + b); 387 | } 388 | 389 | void setURFtoDLF(cubiecube_t* cubiecube, short idx) 390 | { 391 | int x; 392 | corner_t corner6[6] = { URF, UFL, ULB, UBR, DFR, DLF }; 393 | corner_t otherCorner[2] = { DBL, DRB }; 394 | int b = idx % 720; // Permutation 395 | int a = idx / 720; // Combination 396 | int c, j, k; 397 | for(c = 0; c < CORNER_COUNT; c++) 398 | cubiecube->cp[c] = DRB;// Use DRB to invalidate all corners 399 | 400 | for (j = 1; j < 6; j++)// generate permutation from index b 401 | { 402 | k = b % (j + 1); 403 | b /= j + 1; 404 | while (k-- > 0) 405 | rotateRight_corner(corner6, 0, j); 406 | } 407 | x = 5;// generate combination and set corners 408 | for (j = DRB; j >= 0; j--) 409 | if (a - Cnk(j, x + 1) >= 0) { 410 | cubiecube->cp[j] = corner6[x]; 411 | a -= Cnk(j, x-- + 1); 412 | } 413 | x = 0; 414 | for (j = URF; j <= DRB; j++) 415 | if (cubiecube->cp[j] == DRB) 416 | cubiecube->cp[j] = otherCorner[x++]; 417 | } 418 | 419 | int getURtoDF(cubiecube_t* cubiecube) 420 | { 421 | int a = 0, x = 0; 422 | int b = 0, j; 423 | edge_t edge6[6] = { edge_t(0)}; 424 | // compute the index a < (12 choose 6) and the edge permutation. 425 | for (j = UR; j <= BR; j++) 426 | if (cubiecube->ep[j] <= DF) { 427 | a += Cnk(j, x + 1); 428 | edge6[x++] = cubiecube->ep[j]; 429 | } 430 | 431 | for (j = 5; j > 0; j--)// compute the index b < 6! for the 432 | // permutation in edge6 433 | { 434 | int k = 0; 435 | while (edge6[j] != j) { 436 | rotateLeft_edge(edge6, 0, j); 437 | k++; 438 | } 439 | b = (j + 1) * b + k; 440 | } 441 | return 720 * a + b; 442 | } 443 | 444 | void setURtoDF(cubiecube_t* cubiecube, int idx) 445 | { 446 | int x, e, j, k; 447 | edge_t edge6[6] = { UR, UF, UL, UB, DR, DF }; 448 | edge_t otherEdge[6] = { DL, DB, FR, FL, BL, BR }; 449 | int b = idx % 720; // Permutation 450 | int a = idx / 720; // Combination 451 | 452 | for(e = 0; e < EDGE_COUNT; e++) 453 | cubiecube->ep[e] = BR;// Use BR to invalidate all edges 454 | 455 | for (j = 1; j < 6; j++)// generate permutation from index b 456 | { 457 | k = b % (j + 1); 458 | b /= j + 1; 459 | while (k-- > 0) 460 | rotateRight_edge(edge6, 0, j); 461 | } 462 | x = 5;// generate combination and set edges 463 | for (j = BR; j >= 0; j--) 464 | if (a - Cnk(j, x + 1) >= 0) { 465 | cubiecube->ep[j] = edge6[x]; 466 | a -= Cnk(j, x-- + 1); 467 | } 468 | x = 0; // set the remaining edges DL..BR 469 | for (j = UR; j <= BR; j++) 470 | if (cubiecube->ep[j] == BR) 471 | cubiecube->ep[j] = otherEdge[x++]; 472 | } 473 | 474 | short getURtoUL(cubiecube_t* cubiecube) 475 | { 476 | int a = 0, b = 0, x = 0, j; 477 | edge_t edge3[3] = { edge_t(0)}; 478 | // compute the index a < (12 choose 3) and the edge permutation. 479 | for (j = UR; j <= BR; j++) 480 | if (cubiecube->ep[j] <= UL) { 481 | a += Cnk(j, x + 1); 482 | edge3[x++] = cubiecube->ep[j]; 483 | } 484 | 485 | for (j = 2; j > 0; j--)// compute the index b < 3! for the 486 | // permutation in edge3 487 | { 488 | int k = 0; 489 | while (edge3[j] != j) { 490 | rotateLeft_edge(edge3, 0, j); 491 | k++; 492 | } 493 | b = (j + 1) * b + k; 494 | } 495 | return (short) (6 * a + b); 496 | } 497 | 498 | void setURtoUL(cubiecube_t* cubiecube, short idx) 499 | { 500 | int x, e, j, k; 501 | edge_t edge3[3] = { UR, UF, UL }; 502 | int b = idx % 6; // Permutation 503 | int a = idx / 6; // Combination 504 | for(e = 0; e < EDGE_COUNT; e++) { 505 | cubiecube->ep[e] = BR;// Use BR to invalidate all edges 506 | } 507 | 508 | for (j = 1; j < 3; j++) {// generate permutation from index b 509 | k = b % (j + 1); 510 | b /= j + 1; 511 | while (k-- > 0) 512 | rotateRight_edge(edge3, 0, j); 513 | } 514 | x = 2;// generate combination and set edges 515 | for (j = BR; j >= 0; j--) { 516 | if (a - Cnk(j, x + 1) >= 0) { 517 | cubiecube->ep[j] = edge3[x]; 518 | a -= Cnk(j, x-- + 1); 519 | } 520 | } 521 | } 522 | 523 | short getUBtoDF(cubiecube_t* cubiecube) 524 | { 525 | int a = 0, x = 0, b = 0, j; 526 | edge_t edge3[3] = { edge_t(0)}; 527 | // compute the index a < (12 choose 3) and the edge permutation. 528 | for (j = UR; j <= BR; j++) 529 | if (UB <= cubiecube->ep[j] && cubiecube->ep[j] <= DF) { 530 | a += Cnk(j, x + 1); 531 | edge3[x++] = cubiecube->ep[j]; 532 | } 533 | 534 | for (j = 2; j > 0; j--)// compute the index b < 3! for the 535 | // permutation in edge3 536 | { 537 | int k = 0; 538 | while (edge3[j] != UB + j) { 539 | rotateLeft_edge(edge3, 0, j); 540 | k++; 541 | } 542 | b = (j + 1) * b + k; 543 | } 544 | return (short) (6 * a + b); 545 | } 546 | 547 | void setUBtoDF(cubiecube_t* cubiecube, short idx) 548 | { 549 | int x, e, j, k; 550 | edge_t edge3[3] = { UB, DR, DF }; 551 | int b = idx % 6; // Permutation 552 | int a = idx / 6; // Combination 553 | for (e = 0; e < EDGE_COUNT; e++) 554 | cubiecube->ep[e] = BR;// Use BR to invalidate all edges 555 | 556 | for (j = 1; j < 3; j++)// generate permutation from index b 557 | { 558 | k = b % (j + 1); 559 | b /= j + 1; 560 | while (k-- > 0) 561 | rotateRight_edge(edge3, 0, j); 562 | } 563 | x = 2;// generate combination and set edges 564 | for (j = BR; j >= 0; j--) 565 | if (a - Cnk(j, x + 1) >= 0) { 566 | cubiecube->ep[j] = edge3[x]; 567 | a -= Cnk(j, x-- + 1); 568 | } 569 | } 570 | 571 | int getURFtoDLB(cubiecube_t* cubiecube) 572 | { 573 | corner_t perm[8] = { corner_t(0)}; 574 | int b = 0, i, j; 575 | for (i = 0; i < 8; i++) 576 | perm[i] = cubiecube->cp[i]; 577 | for (j = 7; j > 0; j--)// compute the index b < 8! for the permutation in perm 578 | { 579 | int k = 0; 580 | while (perm[j] != j) { 581 | rotateLeft_corner(perm, 0, j); 582 | k++; 583 | } 584 | b = (j + 1) * b + k; 585 | } 586 | return b; 587 | } 588 | 589 | void setURFtoDLB(cubiecube_t* cubiecube, int idx) 590 | { 591 | corner_t perm[8] = { URF, UFL, ULB, UBR, DFR, DLF, DBL, DRB }; 592 | int k, j; 593 | int x = 7;// set corners 594 | for (j = 1; j < 8; j++) { 595 | k = idx % (j + 1); 596 | idx /= j + 1; 597 | while (k-- > 0) 598 | rotateRight_corner(perm, 0, j); 599 | } 600 | 601 | for (j = 7; j >= 0; j--) 602 | cubiecube->cp[j] = perm[x--]; 603 | } 604 | 605 | int getURtoBR(cubiecube_t* cubiecube) 606 | { 607 | edge_t perm[12] = { edge_t(0)}; 608 | int b = 0, i, j; 609 | for (i = 0; i < 12; i++) 610 | perm[i] = cubiecube->ep[i]; 611 | for (j = 11; j > 0; j--)// compute the index b < 12! for the permutation in perm 612 | { 613 | int k = 0; 614 | while (perm[j] != j) { 615 | rotateLeft_edge(perm, 0, j); 616 | k++; 617 | } 618 | b = (j + 1) * b + k; 619 | } 620 | return b; 621 | } 622 | 623 | void setURtoBR(cubiecube_t* cubiecube, int idx) 624 | { 625 | edge_t perm[12] = { UR, UF, UL, UB, DR, DF, DL, DB, FR, FL, BL, BR }; 626 | int k, j; 627 | int x = 11;// set edges 628 | for (j = 1; j < 12; j++) { 629 | k = idx % (j + 1); 630 | idx /= j + 1; 631 | while (k-- > 0) 632 | rotateRight_edge(perm, 0, j); 633 | } 634 | for (j = 11; j >= 0; j--) 635 | cubiecube->ep[j] = perm[x--]; 636 | } 637 | 638 | int verify(cubiecube_t* cubiecube) 639 | { 640 | int sum = 0, e, i, c; 641 | int edgeCount[12] = {0}; 642 | int cornerCount[8] = {0}; 643 | 644 | for(e = 0; e < EDGE_COUNT; e++) 645 | edgeCount[cubiecube->ep[e]]++; 646 | for (i = 0; i < 12; i++) 647 | if (edgeCount[i] != 1) 648 | return -2; 649 | 650 | for (i = 0; i < 12; i++) 651 | sum += cubiecube->eo[i]; 652 | if (sum % 2 != 0) 653 | return -3; 654 | 655 | for(c = 0; c < CORNER_COUNT; c++) 656 | cornerCount[cubiecube->cp[c]]++; 657 | for (i = 0; i < 8; i++) 658 | if (cornerCount[i] != 1) 659 | return -4;// missing corners 660 | 661 | sum = 0; 662 | for (i = 0; i < 8; i++) 663 | sum += cubiecube->co[i]; 664 | if (sum % 3 != 0) 665 | return -5;// twisted corner 666 | 667 | if ((edgeParity(cubiecube) ^ cornerParity(cubiecube)) != 0) 668 | return -6;// parity error 669 | 670 | return 0;// cube ok 671 | } 672 | 673 | int getURtoDF_standalone(short idx1, short idx2) 674 | { 675 | int res, i; 676 | cubiecube_t *a = get_cubiecube(); 677 | cubiecube_t *b = get_cubiecube(); 678 | setURtoUL(a, idx1); 679 | setUBtoDF(b, idx2); 680 | for (i = 0; i < 8; i++) { 681 | if (a->ep[i] != BR) { 682 | if (b->ep[i] != BR) {// collision 683 | return -1; 684 | } else { 685 | b->ep[i] = a->ep[i]; 686 | } 687 | } 688 | } 689 | res = getURtoDF(b); 690 | free(a); 691 | free(b); 692 | return res; 693 | } 694 | -------------------------------------------------------------------------------- /kociemba/cubiecube.h: -------------------------------------------------------------------------------- 1 | #ifndef CUBIECUBE_H 2 | #define CUBIECUBE_H 3 | 4 | #include 5 | #include 6 | 7 | #include "corner.h" 8 | #include "edge.h" 9 | 10 | //Cube on the cubie level 11 | struct cubiecube { 12 | // initialize to Id-Cube 13 | // corner permutation 14 | corner_t cp[8]; 15 | // corner orientation 16 | signed char co[8]; 17 | // edge permutation 18 | edge_t ep[12]; 19 | // edge orientation 20 | signed char eo[12]; 21 | }; 22 | typedef struct cubiecube cubiecube_t; 23 | 24 | // forward declaration 25 | struct facecube; 26 | 27 | // this CubieCube array represents the 6 basic cube moves 28 | cubiecube_t* get_moveCube(void); 29 | cubiecube_t* get_cubiecube(void); 30 | 31 | // n choose k 32 | int Cnk(int n, int k); 33 | void rotateLeft_corner(corner_t* arr, int l, int r); 34 | void rotateRight_corner(corner_t* arr, int l, int r); 35 | void rotateLeft_edge(edge_t* arr, int l, int r); 36 | void rotateRight_edge(edge_t* arr, int l, int r); 37 | struct facecube* toFaceCube(cubiecube_t* cubiecube); 38 | void cornerMultiply(cubiecube_t* cubiecube, cubiecube_t* b); 39 | void edgeMultiply(cubiecube_t* cubiecube, cubiecube_t* b); 40 | void multiply(cubiecube_t* cubiecube, cubiecube_t* b); 41 | void invCubieCube(cubiecube_t* cubiecube, cubiecube_t* c); 42 | short getTwist(cubiecube_t* cubiecube); 43 | void setTwist(cubiecube_t* cubiecube, short twist); 44 | short getFlip(cubiecube_t* cubiecube); 45 | void setFlip(cubiecube_t* cubiecube, short flip); 46 | short cornerParity(cubiecube_t* cubiecube); 47 | short edgeParity(cubiecube_t* cubiecube); 48 | short getFRtoBR(cubiecube_t* cubiecube); 49 | void setFRtoBR(cubiecube_t* cubiecube, short idx); 50 | short getURFtoDLF(cubiecube_t* cubiecube); 51 | void setURFtoDLF(cubiecube_t* cubiecube, short idx); 52 | int getURtoDF(cubiecube_t* cubiecube); 53 | void setURtoDF(cubiecube_t* cubiecube, int idx); 54 | 55 | short getURtoUL(cubiecube_t* cubiecube); 56 | void setURtoUL(cubiecube_t* cubiecube, short idx); 57 | short getUBtoDF(cubiecube_t* cubiecube); 58 | void setUBtoDF(cubiecube_t* cubiecube, short idx); 59 | int getURFtoDLB(cubiecube_t* cubiecube); 60 | void setURFtoDLB(cubiecube_t* cubiecube, int idx); 61 | int getURtoBR(cubiecube_t* cubiecube); 62 | void setURtoBR(cubiecube_t* cubiecube, int idx); 63 | 64 | int verify(cubiecube_t* cubiecube); 65 | 66 | int getURtoDF_standalone(short idx1, short idx2); 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /kociemba/edge.h: -------------------------------------------------------------------------------- 1 | #ifndef EDGE_H 2 | #define EDGE_H 3 | // The names of the edge positions of the cube. Edge UR e.g., has an U(p) and R(ight) facelet. 4 | typedef enum { 5 | UR, UF, UL, UB, DR, DF, DL, DB, FR, FL, BL, BR 6 | } edge_t; 7 | 8 | #define EDGE_COUNT 12 9 | #endif 10 | -------------------------------------------------------------------------------- /kociemba/facecube.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "facecube.h" 4 | #include "cubiecube.h" 5 | 6 | 7 | facelet_t cornerFacelet[8][3] = { { U9, R1, F3 }, { U7, F1, L3 }, { U1, L1, B3 }, { U3, B1, R3 }, 8 | { D3, F9, R7 }, { D1, L9, F7 }, { D7, B9, L7 }, { D9, R9, B7 } }; 9 | 10 | facelet_t edgeFacelet[12][2] = { { U6, R2 }, { U8, F2 }, { U4, L2 }, { U2, B2 }, { D6, R8 }, { D2, F8 }, 11 | { D4, L8 }, { D8, B8 }, { F6, R4 }, { F4, L6 }, { B6, L4 }, { B4, R6 } }; 12 | 13 | color_t cornerColor[8][3] = { { U, R, F }, { U, F, L }, { U, L, B }, { U, B, R }, { D, F, R }, { D, L, F }, 14 | { D, B, L }, { D, R, B } }; 15 | 16 | color_t edgeColor[12][2] = { { U, R }, { U, F }, { U, L }, { U, B }, { D, R }, { D, F }, { D, L }, { D, B }, 17 | { F, R }, { F, L }, { B, L }, { B, R } }; 18 | 19 | 20 | facecube_t* get_facecube() 21 | { 22 | facecube_t* res = (facecube_t *) calloc(1, sizeof(facecube_t)); 23 | static const color_t f[54] = {U, U, U, U, U, U, U, U, U, R, R, R, R, R, R, R, R, R, F, F, F, F, F, F, F, F, F, D, D, D, D, D, D, D, D, D, L, L, L, L, L, L, L, L, L, B, B, B, B, B, B, B, B, B}; 24 | memcpy(res->f, f, sizeof(f)); 25 | return res; 26 | } 27 | 28 | facecube_t* get_facecube_fromstring(char* cubeString) 29 | { 30 | int i; 31 | facecube_t* res = (facecube_t *) calloc(1, sizeof(facecube_t)); 32 | for (i = 0; i < 54; i++) { 33 | switch(cubeString[i]) { 34 | case 'U': 35 | res->f[i] = U; 36 | break; 37 | case 'R': 38 | res->f[i] = R; 39 | break; 40 | case 'F': 41 | res->f[i] = F; 42 | break; 43 | case 'D': 44 | res->f[i] = D; 45 | break; 46 | case 'L': 47 | res->f[i] = L; 48 | break; 49 | case 'B': 50 | res->f[i] = B; 51 | break; 52 | } 53 | } 54 | return res; 55 | } 56 | 57 | void to_String(facecube_t* facecube, char* res) 58 | { 59 | int i; 60 | for (i = 0; i < 54; i++) 61 | switch(facecube->f[i]) { 62 | case U: 63 | res[i] = 'U'; 64 | break; 65 | case R: 66 | res[i] = 'R'; 67 | break; 68 | case F: 69 | res[i] = 'F'; 70 | break; 71 | case D: 72 | res[i] = 'D'; 73 | break; 74 | case L: 75 | res[i] = 'L'; 76 | break; 77 | case B: 78 | res[i] = 'B'; 79 | break; 80 | } 81 | res[54] = 0; 82 | } 83 | 84 | cubiecube_t* toCubieCube(facecube_t* facecube) 85 | { 86 | int i, j; 87 | signed char ori; 88 | color_t col1, col2; 89 | cubiecube_t* ccRet = (cubiecube_t*) calloc(1, sizeof(cubiecube_t)); 90 | for (i = 0; i < 8; i++) 91 | ccRet->cp[i] = URF;// invalidate corners 92 | for (i = 0; i < 12; i++) 93 | ccRet->ep[i] = UR;// and edges 94 | 95 | for(i = 0; i < CORNER_COUNT; i++) { 96 | // get the colors of the cubie at corner i, starting with U/D 97 | for (ori = 0; ori < 3; ori++) 98 | if (facecube->f[cornerFacelet[i][ori]] == U || facecube->f[cornerFacelet[i][ori]] == D) 99 | break; 100 | col1 = facecube->f[cornerFacelet[i][(ori + 1) % 3]]; 101 | col2 = facecube->f[cornerFacelet[i][(ori + 2) % 3]]; 102 | 103 | for (j = 0; j < CORNER_COUNT; j++) { 104 | if (col1 == cornerColor[j][1] && col2 == cornerColor[j][2]) { 105 | // in cornerposition i we have cornercubie j 106 | ccRet->cp[i] = corner_t( j); 107 | ccRet->co[i] = ori % 3; 108 | break; 109 | } 110 | } 111 | } 112 | 113 | for (i = 0; i < EDGE_COUNT; i++) { 114 | for (j = 0; j < EDGE_COUNT; j++) { 115 | if (facecube->f[edgeFacelet[i][0]] == edgeColor[j][0] 116 | && facecube->f[edgeFacelet[i][1]] == edgeColor[j][1]) { 117 | ccRet->ep[i] = edge_t(j); 118 | ccRet->eo[i] = 0; 119 | break; 120 | } 121 | if (facecube->f[edgeFacelet[i][0]] == edgeColor[j][1] 122 | && facecube->f[edgeFacelet[i][1]] == edgeColor[j][0]) { 123 | ccRet->ep[i] = edge_t(j); 124 | ccRet->eo[i] = 1; 125 | break; 126 | } 127 | } 128 | } 129 | return ccRet; 130 | } 131 | -------------------------------------------------------------------------------- /kociemba/facecube.h: -------------------------------------------------------------------------------- 1 | #ifndef FACECUBE_H 2 | #define FACECUBE_H 3 | 4 | #include "facelet.h" 5 | #include "color.h" 6 | #include "corner.h" 7 | #include "edge.h" 8 | 9 | //Cube on the facelet level 10 | struct facecube { 11 | color_t f[54]; 12 | }; 13 | typedef struct facecube facecube_t; 14 | 15 | // forward declaration 16 | struct cubiecube; 17 | 18 | // Map the corner positions to facelet positions. cornerFacelet[URF.ordinal()][0] e.g. gives the position of the 19 | // facelet in the URF corner position, which defines the orientation.
20 | // cornerFacelet[URF.ordinal()][1] and cornerFacelet[URF.ordinal()][2] give the position of the other two facelets 21 | // of the URF corner (clockwise). 22 | extern facelet_t cornerFacelet[8][3]; 23 | 24 | // Map the edge positions to facelet positions. edgeFacelet[UR.ordinal()][0] e.g. gives the position of the facelet in 25 | // the UR edge position, which defines the orientation.
26 | // edgeFacelet[UR.ordinal()][1] gives the position of the other facelet 27 | extern facelet_t edgeFacelet[12][2]; 28 | 29 | // Map the corner positions to facelet colors. 30 | extern color_t cornerColor[8][3]; 31 | 32 | // Map the edge positions to facelet colors. 33 | extern color_t edgeColor[12][2]; 34 | 35 | facecube_t* get_facecube(void); 36 | facecube_t* get_facecube_fromstring(char* cubeString); 37 | 38 | void to_String(facecube_t* facecube, char* res); 39 | struct cubiecube* toCubieCube(facecube_t* facecube); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /kociemba/facelet.h: -------------------------------------------------------------------------------- 1 | #ifndef FACELET_H 2 | #define FACELET_H 3 | 4 | /** 5 | *
 6 |  * The names of the facelet positions of the cube
 7 |  *             |************|
 8 |  *             |*U1**U2**U3*|
 9 |  *             |************|
10 |  *             |*U4**U5**U6*|
11 |  *             |************|
12 |  *             |*U7**U8**U9*|
13 |  *             |************|
14 |  * ************|************|************|************|
15 |  * *L1**L2**L3*|*F1**F2**F3*|*R1**R2**F3*|*B1**B2**B3*|
16 |  * ************|************|************|************|
17 |  * *L4**L5**L6*|*F4**F5**F6*|*R4**R5**R6*|*B4**B5**B6*|
18 |  * ************|************|************|************|
19 |  * *L7**L8**L9*|*F7**F8**F9*|*R7**R8**R9*|*B7**B8**B9*|
20 |  * ************|************|************|************|
21 |  *             |************|
22 |  *             |*D1**D2**D3*|
23 |  *             |************|
24 |  *             |*D4**D5**D6*|
25 |  *             |************|
26 |  *             |*D7**D8**D9*|
27 |  *             |************|
28 |  * 
29 | * 30 | *A cube definition string "UBL..." means for example: In position U1 we have the U-color, in position U2 we have the 31 | * B-color, in position U3 we have the L color etc. according to the order U1, U2, U3, U4, U5, U6, U7, U8, U9, R1, R2, 32 | * R3, R4, R5, R6, R7, R8, R9, F1, F2, F3, F4, F5, F6, F7, F8, F9, D1, D2, D3, D4, D5, D6, D7, D8, D9, L1, L2, L3, L4, 33 | * L5, L6, L7, L8, L9, B1, B2, B3, B4, B5, B6, B7, B8, B9 of the enum constants. 34 | */ 35 | typedef enum { 36 | U1, U2, U3, U4, U5, U6, U7, U8, U9, R1, R2, R3, R4, R5, R6, R7, R8, R9, F1, F2, F3, F4, F5, F6, F7, F8, F9, D1, D2, D3, D4, D5, D6, D7, D8, D9, L1, L2, L3, L4, L5, L6, L7, L8, L9, B1, B2, B3, B4, B5, B6, B7, B8, B9 37 | } facelet_t; 38 | 39 | #define FACELET_COUNT 54 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /kociemba/prunetable_helpers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "prunetable_helpers.h" 7 | 8 | char * join_path(const char *dir, const char *filename) 9 | { 10 | size_t path_len = strnlen(dir, 500); 11 | char *fpath = (char *)calloc(path_len + 32, 1); 12 | if (path_len == 500) { 13 | return NULL; 14 | } 15 | strcpy(fpath, dir); 16 | strcat(fpath, "/"); 17 | strncat(fpath, filename, 30); 18 | return fpath; 19 | } 20 | 21 | int check_cached_table(const char* name, void* ptr, int len, const char *cache_dir) 22 | { 23 | int res = 0; 24 | char *fname = join_path(cache_dir, name); 25 | if (fname == NULL) { 26 | fprintf(stderr, "Path to cache tables is too long\n"); 27 | return -1; 28 | } 29 | 30 | if (access(fname, F_OK | R_OK) != -1) { 31 | // fprintf(stderr, "Found cache for %s. Loading...", name); 32 | read_from_file(ptr, len, fname); 33 | // fprintf(stderr, "done.\n"); 34 | res = 0; 35 | } else { 36 | fprintf(stderr, "Cache table %s was not found. Recalculating.\n", fname); 37 | res = 1; 38 | } 39 | free(fname); 40 | return res; 41 | } 42 | 43 | void read_from_file(void* ptr, int len, const char* name) 44 | { 45 | FILE* f = fopen(name, "rb"); 46 | if (!fread(ptr, len, 1, f)) 47 | ((void)0); // suppress -Wunused-result warning 48 | fclose(f); 49 | } 50 | 51 | int make_dir(const char *cache_dir) 52 | { 53 | #if defined(_WIN32) 54 | return _mkdir(cache_dir); 55 | #else 56 | return mkdir(cache_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 57 | #endif 58 | } 59 | 60 | void dump_to_file(void* ptr, int len, const char* name, const char *cache_dir) 61 | { 62 | int status; 63 | status = make_dir(cache_dir); 64 | if (status == 0 || errno == EEXIST) { 65 | char *fname = join_path(cache_dir, name); 66 | if (fname == NULL) { 67 | fprintf(stderr, "Path to cache tables is too long\n"); 68 | } else { 69 | FILE* f = fopen(fname, "wb"); 70 | fwrite(ptr, len, 1, f); 71 | free(fname); 72 | fclose(f); 73 | } 74 | } else { 75 | fprintf(stderr, "cannot create cache tables directory\n"); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /kociemba/prunetable_helpers.h: -------------------------------------------------------------------------------- 1 | #ifndef PRUNETABLE_HELPERS_H 2 | #define PRUNETABLE_HELPERS_H 3 | 4 | #if defined(_WIN32) 5 | #include 6 | #include "direct.h" 7 | #define R_OK 4 /* Test for read permission. */ 8 | #define W_OK 2 /* Test for write permission. */ 9 | #define X_OK 1 /* Test for execute permission. */ 10 | #define F_OK 0 /* Test for existence. */ 11 | #define access _access 12 | #else 13 | #include 14 | #endif 15 | 16 | int make_dir(const char *cache_dir); 17 | int check_cached_table(const char* name, void* ptr, int len, const char *cache_dir); 18 | void dump_to_file(void* ptr, int len, const char* name, const char *cache_dir); 19 | void read_from_file(void* ptr, int len, const char* name); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /kociemba/search.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "search.h" 5 | #include "color.h" 6 | #include "facecube.h" 7 | #include "coordcube.h" 8 | 9 | #define MIN(a, b) (((a)<(b))?(a):(b)) 10 | #define MAX(a, b) (((a)>(b))?(a):(b)) 11 | 12 | char* solutionToString(search_t* search, int length, int depthPhase1) 13 | { 14 | char* s = (char*) calloc(length * 3 + 5, 1); 15 | int cur = 0, i; 16 | for (i = 0; i < length; i++) { 17 | switch (search->ax[i]) { 18 | case 0: 19 | s[cur++] = 'U'; 20 | break; 21 | case 1: 22 | s[cur++] = 'R'; 23 | break; 24 | case 2: 25 | s[cur++] = 'F'; 26 | break; 27 | case 3: 28 | s[cur++] = 'D'; 29 | break; 30 | case 4: 31 | s[cur++] = 'L'; 32 | break; 33 | case 5: 34 | s[cur++] = 'B'; 35 | break; 36 | } 37 | switch (search->po[i]) { 38 | case 1: 39 | s[cur++] = ' '; 40 | break; 41 | case 2: 42 | s[cur++] = '2'; 43 | s[cur++] = ' '; 44 | break; 45 | case 3: 46 | s[cur++] = '\''; 47 | s[cur++] = ' '; 48 | break; 49 | } 50 | if (i == depthPhase1 - 1) { 51 | s[cur++] = '.'; 52 | s[cur++] = ' '; 53 | } 54 | } 55 | return s; 56 | } 57 | 58 | 59 | char* solution(char* facelets, int maxDepth, long timeOut, int useSeparator, const char* cache_dir) 60 | { 61 | search_t* search = (search_t*) calloc(1, sizeof(search_t)); 62 | facecube_t* fc; 63 | cubiecube_t* cc; 64 | coordcube_t* c; 65 | 66 | int s, i; 67 | int mv, n; 68 | int busy; 69 | int depthPhase1; 70 | time_t tStart; 71 | // +++++++++++++++++++++check for wrong input +++++++++++++++++++++++++++++ 72 | int count[6] = {0}; 73 | 74 | if (PRUNING_INITED == 0) { 75 | initPruning(cache_dir); 76 | } 77 | 78 | for (i = 0; i < 54; i++) 79 | switch(facelets[i]) { 80 | case 'U': 81 | count[U]++; 82 | break; 83 | case 'R': 84 | count[R]++; 85 | break; 86 | case 'F': 87 | count[F]++; 88 | break; 89 | case 'D': 90 | count[D]++; 91 | break; 92 | case 'L': 93 | count[L]++; 94 | break; 95 | case 'B': 96 | count[B]++; 97 | break; 98 | } 99 | 100 | for (i = 0; i < 6; i++) 101 | if (count[i] != 9) { 102 | free(search); 103 | return NULL; 104 | } 105 | 106 | fc = get_facecube_fromstring(facelets); 107 | cc = toCubieCube(fc); 108 | if ((s = verify(cc)) != 0) { 109 | free(search); 110 | return NULL; 111 | } 112 | 113 | // +++++++++++++++++++++++ initialization +++++++++++++++++++++++++++++++++ 114 | c = get_coordcube(cc); 115 | 116 | search->po[0] = 0; 117 | search->ax[0] = 0; 118 | search->flip[0] = c->flip; 119 | search->twist[0] = c->twist; 120 | search->parity[0] = c->parity; 121 | search->slice[0] = c->FRtoBR / 24; 122 | search->URFtoDLF[0] = c->URFtoDLF; 123 | search->FRtoBR[0] = c->FRtoBR; 124 | search->URtoUL[0] = c->URtoUL; 125 | search->UBtoDF[0] = c->UBtoDF; 126 | 127 | search->minDistPhase1[1] = 1;// else failure for depth=1, n=0 128 | mv = 0; 129 | n = 0; 130 | busy = 0; 131 | depthPhase1 = 1; 132 | 133 | tStart = time(NULL); 134 | 135 | // +++++++++++++++++++ Main loop ++++++++++++++++++++++++++++++++++++++++++ 136 | do { 137 | do { 138 | if ((depthPhase1 - n > search->minDistPhase1[n + 1]) && !busy) { 139 | 140 | if (search->ax[n] == 0 || search->ax[n] == 3)// Initialize next move 141 | search->ax[++n] = 1; 142 | else 143 | search->ax[++n] = 0; 144 | search->po[n] = 1; 145 | } else if (++search->po[n] > 3) { 146 | do {// increment axis 147 | if (++search->ax[n] > 5) { 148 | 149 | if (time(NULL) - tStart > timeOut) 150 | return NULL; 151 | 152 | if (n == 0) { 153 | if (depthPhase1 >= maxDepth) 154 | return NULL; 155 | else { 156 | depthPhase1++; 157 | search->ax[n] = 0; 158 | search->po[n] = 1; 159 | busy = 0; 160 | break; 161 | } 162 | } else { 163 | n--; 164 | busy = 1; 165 | break; 166 | } 167 | 168 | } else { 169 | search->po[n] = 1; 170 | busy = 0; 171 | } 172 | } while (n != 0 && (search->ax[n - 1] == search->ax[n] || search->ax[n - 1] - 3 == search->ax[n])); 173 | } else 174 | busy = 0; 175 | } while (busy); 176 | 177 | // +++++++++++++ compute new coordinates and new minDistPhase1 ++++++++++ 178 | // if minDistPhase1 =0, the H subgroup is reached 179 | mv = 3 * search->ax[n] + search->po[n] - 1; 180 | search->flip[n + 1] = flipMove[search->flip[n]][mv]; 181 | search->twist[n + 1] = twistMove[search->twist[n]][mv]; 182 | search->slice[n + 1] = FRtoBR_Move[search->slice[n] * 24][mv] / 24; 183 | search->minDistPhase1[n + 1] = MAX( 184 | getPruning(Slice_Flip_Prun, N_SLICE1 * search->flip[n + 1] + search->slice[n + 1]), 185 | getPruning(Slice_Twist_Prun, N_SLICE1 * search->twist[n + 1] + search->slice[n + 1]) 186 | ); 187 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 188 | // System.out.format("%d %d\n", n, depthPhase1); 189 | if (search->minDistPhase1[n + 1] == 0 && n >= depthPhase1 - 5) { 190 | search->minDistPhase1[n + 1] = 10;// instead of 10 any value >5 is possible 191 | if (n == depthPhase1 - 1 && (s = totalDepth(search, depthPhase1, maxDepth)) >= 0) { 192 | if (s == depthPhase1 193 | || (search->ax[depthPhase1 - 1] != search->ax[depthPhase1] && search->ax[depthPhase1 - 1] != search->ax[depthPhase1] + 3)) { 194 | char* res; 195 | free((void*) fc); 196 | free((void*) cc); 197 | free((void*) c); 198 | if (useSeparator) { 199 | res = solutionToString(search, s, depthPhase1); 200 | } else { 201 | res = solutionToString(search, s, -1); 202 | } 203 | free((void*) search); 204 | return res; 205 | } 206 | } 207 | 208 | } 209 | } while (1); 210 | } 211 | 212 | int totalDepth(search_t* search, int depthPhase1, int maxDepth) 213 | { 214 | int mv = 0, d1 = 0, d2 = 0, i; 215 | int maxDepthPhase2 = MIN(10, maxDepth - depthPhase1);// Allow only max 10 moves in phase2 216 | int depthPhase2; 217 | int n; 218 | int busy; 219 | for (i = 0; i < depthPhase1; i++) { 220 | mv = 3 * search->ax[i] + search->po[i] - 1; 221 | // System.out.format("%d %d %d %d\n", i, mv, ax[i], po[i]); 222 | search->URFtoDLF[i + 1] = URFtoDLF_Move[search->URFtoDLF[i]][mv]; 223 | search->FRtoBR[i + 1] = FRtoBR_Move[search->FRtoBR[i]][mv]; 224 | search->parity[i + 1] = parityMove[search->parity[i]][mv]; 225 | } 226 | 227 | if ((d1 = getPruning(Slice_URFtoDLF_Parity_Prun, 228 | (N_SLICE2 * search->URFtoDLF[depthPhase1] + search->FRtoBR[depthPhase1]) * 2 + search->parity[depthPhase1])) > maxDepthPhase2) 229 | return -1; 230 | 231 | for (i = 0; i < depthPhase1; i++) { 232 | mv = 3 * search->ax[i] + search->po[i] - 1; 233 | search->URtoUL[i + 1] = URtoUL_Move[search->URtoUL[i]][mv]; 234 | search->UBtoDF[i + 1] = UBtoDF_Move[search->UBtoDF[i]][mv]; 235 | } 236 | search->URtoDF[depthPhase1] = MergeURtoULandUBtoDF[search->URtoUL[depthPhase1]][search->UBtoDF[depthPhase1]]; 237 | 238 | if ((d2 = getPruning(Slice_URtoDF_Parity_Prun, 239 | (N_SLICE2 * search->URtoDF[depthPhase1] + search->FRtoBR[depthPhase1]) * 2 + search->parity[depthPhase1])) > maxDepthPhase2) 240 | return -1; 241 | 242 | if ((search->minDistPhase2[depthPhase1] = MAX(d1, d2)) == 0)// already solved 243 | return depthPhase1; 244 | 245 | // now set up search 246 | 247 | depthPhase2 = 1; 248 | n = depthPhase1; 249 | busy = 0; 250 | search->po[depthPhase1] = 0; 251 | search->ax[depthPhase1] = 0; 252 | search->minDistPhase2[n + 1] = 1;// else failure for depthPhase2=1, n=0 253 | // +++++++++++++++++++ end initialization +++++++++++++++++++++++++++++++++ 254 | do { 255 | do { 256 | if ((depthPhase1 + depthPhase2 - n > search->minDistPhase2[n + 1]) && !busy) { 257 | 258 | if (search->ax[n] == 0 || search->ax[n] == 3)// Initialize next move 259 | { 260 | search->ax[++n] = 1; 261 | search->po[n] = 2; 262 | } else { 263 | search->ax[++n] = 0; 264 | search->po[n] = 1; 265 | } 266 | } else if ((search->ax[n] == 0 || search->ax[n] == 3) ? (++search->po[n] > 3) : ((search->po[n] = search->po[n] + 2) > 3)) { 267 | do {// increment axis 268 | if (++search->ax[n] > 5) { 269 | if (n == depthPhase1) { 270 | if (depthPhase2 >= maxDepthPhase2) 271 | return -1; 272 | else { 273 | depthPhase2++; 274 | search->ax[n] = 0; 275 | search->po[n] = 1; 276 | busy = 0; 277 | break; 278 | } 279 | } else { 280 | n--; 281 | busy = 1; 282 | break; 283 | } 284 | 285 | } else { 286 | if (search->ax[n] == 0 || search->ax[n] == 3) 287 | search->po[n] = 1; 288 | else 289 | search->po[n] = 2; 290 | busy = 0; 291 | } 292 | } while (n != depthPhase1 && (search->ax[n - 1] == search->ax[n] || search->ax[n - 1] - 3 == search->ax[n])); 293 | } else 294 | busy = 0; 295 | } while (busy); 296 | // +++++++++++++ compute new coordinates and new minDist ++++++++++ 297 | mv = 3 * search->ax[n] + search->po[n] - 1; 298 | 299 | search->URFtoDLF[n + 1] = URFtoDLF_Move[search->URFtoDLF[n]][mv]; 300 | search->FRtoBR[n + 1] = FRtoBR_Move[search->FRtoBR[n]][mv]; 301 | search->parity[n + 1] = parityMove[search->parity[n]][mv]; 302 | search->URtoDF[n + 1] = URtoDF_Move[search->URtoDF[n]][mv]; 303 | 304 | search->minDistPhase2[n + 1] = MAX(getPruning(Slice_URtoDF_Parity_Prun, (N_SLICE2 305 | * search->URtoDF[n + 1] + search->FRtoBR[n + 1]) 306 | * 2 + search->parity[n + 1]), getPruning(Slice_URFtoDLF_Parity_Prun, (N_SLICE2 307 | * search->URFtoDLF[n + 1] + search->FRtoBR[n + 1]) 308 | * 2 + search->parity[n + 1])); 309 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 310 | 311 | } while (search->minDistPhase2[n + 1] != 0); 312 | return depthPhase1 + depthPhase2; 313 | } 314 | 315 | void patternize(char* facelets, char* pattern, char* patternized) 316 | { 317 | facecube_t* fc; 318 | facecube_t* start_fc = get_facecube_fromstring(facelets); 319 | facecube_t* pattern_fc = get_facecube_fromstring(pattern); 320 | cubiecube_t* start_cc = toCubieCube(start_fc); 321 | cubiecube_t* pattern_cc = toCubieCube(pattern_fc); 322 | cubiecube_t* inv_pattern_cc = get_cubiecube(); 323 | invCubieCube(pattern_cc, inv_pattern_cc); 324 | multiply(inv_pattern_cc, start_cc); 325 | fc = toFaceCube(inv_pattern_cc); 326 | to_String(fc, patternized); 327 | free(start_fc); 328 | free(pattern_fc); 329 | free(start_cc); 330 | free(pattern_cc); 331 | free(inv_pattern_cc); 332 | free(fc); 333 | } 334 | -------------------------------------------------------------------------------- /kociemba/search.h: -------------------------------------------------------------------------------- 1 | #ifndef SEARCH_H 2 | #define SEARCH_H 3 | 4 | typedef struct { 5 | int ax[31]; // The axis of the move 6 | int po[31]; // The power of the move 7 | int flip[31]; // phase1 coordinates 8 | int twist[31]; 9 | int slice[31]; 10 | int parity[31]; // phase2 coordinates 11 | int URFtoDLF[31]; 12 | int FRtoBR[31]; 13 | int URtoUL[31]; 14 | int UBtoDF[31]; 15 | int URtoDF[31]; 16 | int minDistPhase1[31]; // IDA* distance do goal estimations 17 | int minDistPhase2[31]; 18 | } search_t; 19 | 20 | search_t* get_search(void); 21 | 22 | // generate the solution string from the array data including a separator between phase1 and phase2 moves 23 | char* solutionToString(search_t* search, int length, int depthPhase1); 24 | /** 25 | * Computes the solver string for a given cube. 26 | * 27 | * @param facelets 28 | * is the cube definition string, see {@link Facelet} for the format. 29 | * 30 | * @param maxDepth 31 | * defines the maximal allowed maneuver length. For random cubes, a maxDepth of 21 usually will return a 32 | * solution in less than 0.5 seconds. With a maxDepth of 20 it takes a few seconds on average to find a 33 | * solution, but it may take much longer for specific cubes. 34 | * 35 | *@param timeOut 36 | * defines the maximum computing time of the method in seconds. If it does not return with a solution, it returns with 37 | * an error code. 38 | * 39 | * @param useSeparator 40 | * determines if a " . " separates the phase1 and phase2 parts of the solver string like in F' R B R L2 F . 41 | * U2 U D for example.
42 | * @return The solution string or an error code:
43 | * Error 1: There is not exactly one facelet of each colour
44 | * Error 2: Not all 12 edges exist exactly once
45 | * Error 3: Flip error: One edge has to be flipped
46 | * Error 4: Not all corners exist exactly once
47 | * Error 5: Twist error: One corner has to be twisted
48 | * Error 6: Parity error: Two corners or two edges have to be exchanged
49 | * Error 7: No solution exists for the given maxDepth
50 | * Error 8: Timeout, no solution within given time 51 | */ 52 | char* solution(char* facelets, int maxDepth, long timeOut, int useSeparator, const char* cache_dir); 53 | 54 | // Apply phase2 of algorithm and return the combined phase1 and phase2 depth. In phase2, only the moves 55 | // U,D,R2,F2,L2 and B2 are allowed. 56 | int totalDepth(search_t* search, int depthPhase1, int maxDepth); 57 | 58 | 59 | // Add a pattern to the state of a cube, so that the solution for new_facelets 60 | // applied to facelets will result into the given pattern 61 | void patternize(char* facelets, char* pattern, char* patternized); 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /kociemba/solve.cpp: -------------------------------------------------------------------------------- 1 | //#include 2 | //#include 3 | //#include "search.h" 4 | // 5 | //int main(int argc, char **argv) 6 | //{ 7 | // argc = 2; 8 | // argv[1] = "RUURULDDLDFRRRFBBRLRBLFUDFLRDULDUFDFFBFDLBUUBBFURBLDBL"; 9 | // if (argc > 1) { 10 | // char patternized[64]; 11 | // char* facelets = argv[1]; 12 | // if (argc > 2) { 13 | // patternize(facelets, argv[2], patternized); 14 | // facelets = patternized; 15 | // } 16 | // char *sol = solution( 17 | // facelets, 18 | // 21, 19 | // 1000, 20 | // 0, 21 | // "cache" 22 | // ); 23 | // if (sol == NULL) { 24 | // puts("Unsolvable cube!"); 25 | // return 2; 26 | // } 27 | // puts(sol); 28 | // free(sol); 29 | // system("pause"); 30 | // return 0; 31 | // } else { 32 | // return 1; 33 | // } 34 | //} 35 | -------------------------------------------------------------------------------- /kociemba/umm: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /vision/mend.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cubhe/cubesolver/d7dd64d3764e32285cdffbeac0e4452a9bee9331/vision/mend.cpp -------------------------------------------------------------------------------- /vision/mend.h: -------------------------------------------------------------------------------- 1 | #ifndef MEND_H 2 | #define MEND_H 3 | #include 4 | using std::string; 5 | void MendCubeCenter(string & str); 6 | void MendCubeCorner(string & str); 7 | void MendCubeEdge(string & str); 8 | void ChangeColor(string & str); 9 | #endif // !MEND_H -------------------------------------------------------------------------------- /vision/vision.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cubhe/cubesolver/d7dd64d3764e32285cdffbeac0e4452a9bee9331/vision/vision.cpp -------------------------------------------------------------------------------- /vision/vision.h: -------------------------------------------------------------------------------- 1 | #ifndef VISION_H 2 | #define SOLVE_H 3 | #include 4 | std::string vision(); 5 | void training(); 6 | #endif // !VISION_H 7 | -------------------------------------------------------------------------------- /vision/源.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include"vision.h" 4 | using namespace std; 5 | int main() { 6 | string color=ReadColor(); 7 | if (color.length() != 0) { 8 | cout <