/// <summary> /// Finds all possible algorithms for this pattern /// </summary> /// <param name="p">Current rubik pattern</param> /// <param name="rotationLayer">Transformation rotation</param> /// <returns>Returns all possible solutions for this pattern</returns> public Dictionary<Pattern, Algorithm> FindMatches(Pattern p, CubeFlag rotationLayer, PatternFilter filter) { Dictionary<Pattern, Algorithm> transformedPatterns = Patterns.ToDictionary(kvp => kvp.Key.DeepClone(), a => a.Value); // clone Dictionary<Pattern,Algorithm> filteredPatterns = transformedPatterns.Where(kvp => filter.Filter(p, kvp.Key)).ToDictionary(pa => pa.Key, a => a.Value); // filter filteredPatterns = filteredPatterns.OrderByDescending(k => k.Key.Probability).ToDictionary(pa => pa.Key.DeepClone(), a => a.Value); // order by probability Dictionary<Pattern, Algorithm> matches = new Dictionary<Pattern, Algorithm>(); // 4 possible standard transformations for (int i = 0; i < 4; i++) { // Get matches foreach (KeyValuePair<Pattern, Algorithm> kvp in filteredPatterns.Where(pa => p.IncludesAllPatternElements(pa.Key))) { matches.Add(kvp.Key, kvp.Value); // Add to matches } if (rotationLayer == CubeFlag.None) return matches; if (filter.OnlyAtBeginning) { transformedPatterns = filteredPatterns.Except(matches).ToDictionary(pa => pa.Key.Transform(rotationLayer), a => a.Value.Transform(rotationLayer)); filteredPatterns = transformedPatterns; } else { transformedPatterns = transformedPatterns.ToDictionary(pa => pa.Key.Transform(rotationLayer), a => a.Value.Transform(rotationLayer)); filteredPatterns = transformedPatterns.Where(kvp => filter.Filter(p, kvp.Key)).ToDictionary(pa => pa.Key, a => a.Value); } } return matches; }
// **** METHODS **** public static Rubik FromPattern(Pattern pattern) { Rubik rubik = new Rubik(); foreach (PatternItem item in pattern.Items) { if (CubePosition.IsCorner(item.CurrentPosition.Flags)) { bool xyzCorrect = !((item.CurrentPosition.Y == CubeFlag.TopLayer ^ (item.CurrentPosition.X == CubeFlag.RightSlice ^ item.CurrentPosition.Z == CubeFlag.FrontSlice)) ^ (CubeFlagService.FirstYFlag(item.TargetPosition) == CubeFlag.TopLayer ^ (CubeFlagService.FirstXFlag(item.TargetPosition) == CubeFlag.RightSlice ^ CubeFlagService.FirstZFlag(item.TargetPosition) == CubeFlag.FrontSlice))); if (item.CurrentOrientation == Orientation.Correct) { rubik.SetFaceColor(item.CurrentPosition.Flags, CubeFlagService.ToFacePosition(item.CurrentPosition.Y), rubik.GetSliceColor(CubeFlagService.FirstYFlag(item.TargetPosition))); FacePosition x = xyzCorrect ? CubeFlagService.ToFacePosition(item.CurrentPosition.X) : CubeFlagService.ToFacePosition(item.CurrentPosition.Z); FacePosition z = xyzCorrect ? CubeFlagService.ToFacePosition(item.CurrentPosition.Z) : CubeFlagService.ToFacePosition(item.CurrentPosition.X); rubik.SetFaceColor(item.CurrentPosition.Flags, x, rubik.GetSliceColor(CubeFlagService.FirstXFlag(item.TargetPosition))); rubik.SetFaceColor(item.CurrentPosition.Flags, z, rubik.GetSliceColor(CubeFlagService.FirstZFlag(item.TargetPosition))); } else { bool corr = (item.CurrentPosition.X == CubeFlag.RightSlice ^ item.CurrentPosition.Z == CubeFlag.BackSlice) ^ item.CurrentPosition.Y == CubeFlag.BottomLayer; FacePosition x = (corr ^ item.CurrentOrientation == Orientation.Clockwise) ? CubeFlagService.ToFacePosition(item.CurrentPosition.X) : CubeFlagService.ToFacePosition(item.CurrentPosition.Y); FacePosition y = (corr ^ item.CurrentOrientation == Orientation.Clockwise) ? CubeFlagService.ToFacePosition(item.CurrentPosition.Z) : CubeFlagService.ToFacePosition(item.CurrentPosition.X); FacePosition z = (corr ^ item.CurrentOrientation == Orientation.Clockwise) ? CubeFlagService.ToFacePosition(item.CurrentPosition.Y) : CubeFlagService.ToFacePosition(item.CurrentPosition.Z); rubik.SetFaceColor(item.CurrentPosition.Flags, x, rubik.GetSliceColor(CubeFlagService.FirstXFlag(item.TargetPosition))); rubik.SetFaceColor(item.CurrentPosition.Flags, y, rubik.GetSliceColor(CubeFlagService.FirstYFlag(item.TargetPosition))); rubik.SetFaceColor(item.CurrentPosition.Flags, z, rubik.GetSliceColor(CubeFlagService.FirstZFlag(item.TargetPosition))); } } if (CubePosition.IsEdge(item.CurrentPosition.Flags)) { CubeFlag flagOne = CubeFlagService.FirstNotInvalidFlag(item.CurrentPosition.Flags, CubeFlag.MiddleLayer | CubeFlag.MiddleSlice | CubeFlag.MiddleSliceSides); FacePosition faceOne = CubeFlagService.ToFacePosition(flagOne); FacePosition faceTwo = CubeFlagService.ToFacePosition(CubeFlagService.FirstNotInvalidFlag(item.CurrentPosition.Flags, CubeFlag.MiddleLayer | CubeFlag.MiddleSlice | CubeFlag.MiddleSliceSides | flagOne)); CubeFlag tFlagOne = CubeFlagService.FirstNotInvalidFlag(item.TargetPosition, CubeFlag.MiddleLayer | CubeFlag.MiddleSlice | CubeFlag.MiddleSliceSides); rubik.SetFaceColor(item.CurrentPosition.Flags, faceOne, rubik.GetSliceColor(tFlagOne)); rubik.SetFaceColor(item.CurrentPosition.Flags, faceTwo, rubik.GetSliceColor(CubeFlagService.FirstNotInvalidFlag(item.TargetPosition, CubeFlag.MiddleLayer | CubeFlag.MiddleSlice | CubeFlag.MiddleSliceSides | tFlagOne))); if (Solvability.GetOrientation(rubik, rubik.Cubes.First(c => c.Position.Flags == item.CurrentPosition.Flags)) != item.CurrentOrientation) { rubik.SetFaceColor(item.CurrentPosition.Flags, faceTwo, rubik.GetSliceColor(tFlagOne)); rubik.SetFaceColor(item.CurrentPosition.Flags, faceOne, rubik.GetSliceColor(CubeFlagService.FirstNotInvalidFlag(item.TargetPosition, CubeFlag.MiddleLayer | CubeFlag.MiddleSlice | CubeFlag.MiddleSliceSides | tFlagOne))); } } if (CubePosition.IsCenter(item.CurrentPosition.Flags)) { CubeFlag flag = CubeFlagService.FirstNotInvalidFlag(item.CurrentPosition.Flags, CubeFlag.MiddleLayer | CubeFlag.MiddleSlice | CubeFlag.MiddleSliceSides); CubeFlag tFlag = CubeFlagService.FirstNotInvalidFlag(item.TargetPosition, CubeFlag.MiddleLayer | CubeFlag.MiddleSlice | CubeFlag.MiddleSliceSides); rubik.SetFaceColor(item.CurrentPosition.Flags, CubeFlagService.ToFacePosition(flag), rubik.GetSliceColor(tFlag)); } } return rubik; }
/// <summary> /// True, if this pattern includes all the pattern elements of another pattern /// </summary> /// <param name="pattern">Pattern to compare</param> public bool IncludesAllPatternElements(Pattern pattern) { foreach (PatternItem item in pattern.Items) { if (!Items.Any(i => i.Equals(item))) return false; } return true; }
/// <summary> /// True, if this pattern has exactly the same pattern elemnts as the other pattern /// </summary> /// <param name="pattern">Pattern to compare</param> public bool Equals(Pattern pattern) { return CollectionMethods.ScrambledEquals(pattern.Items, Items); }
/// <summary> /// Converts a rubik to a pattern /// </summary> /// <param name="r">Rubik </param> /// <returns>The pattern of the given rubik</returns> public static Pattern FromRubik(Rubik r) { Pattern p = new Pattern(); List<PatternItem> newItems = new List<PatternItem>(); foreach (CubePosition pos in Positions) { Cube cube = r.Cubes.First(c => r.GetTargetFlags(c) == pos.Flags); newItems.Add(new PatternItem(cube.Position, Solvability.GetOrientation(r, cube), pos.Flags)); } p.Items = newItems; return p; }
/// <summary> /// Searches for the best algorithm for the given pattern /// </summary> /// <param name="p">Current rubik pattern</param> /// <param name="rotationLayer">Transformation layer</param> /// <returns>Returns the best match</returns> public Algorithm FindBestMatch(Pattern p, CubeFlag rotationLayer, PatternFilter filter) { Dictionary<Pattern, Algorithm> matches = FindMatches(p, rotationLayer, filter); Algorithm bestAlgo = matches.OrderByDescending(item => item.Key.Items.Count()).FirstOrDefault().Value; return bestAlgo; }
/// <summary> /// Searches for the best algorithm for the given pattern /// </summary> /// <param name="p">Current rubik pattern</param> /// <param name="rotationLayer">Transformation layer</param> /// <param name="filter"></param> /// <returns>Returns the best match</returns> public Algorithm FindBestMatch(Pattern p, CubeFlag rotationLayer, PatternFilter filter) { var matches = this.FindMatches(p, rotationLayer, filter); var bestAlgo = matches.OrderByDescending(item => item.Key.Items.Count).FirstOrDefault().Value; return bestAlgo; }