| | 1 | | // -------------------------------------------------------------------------------- |
| | 2 | | // Copyright (C) 2025 Eugene Eremeev (also known as Yevhenii Yeriemeieiv). |
| | 3 | | // All Rights Reserved. |
| | 4 | | // -------------------------------------------------------------------------------- |
| | 5 | | // This software is the confidential and proprietary information of Eugene Eremeev |
| | 6 | | // (also known as Yevhenii Yeriemeieiv) ("Confidential Information"). You shall not |
| | 7 | | // disclose such Confidential Information and shall use it only in accordance with |
| | 8 | | // the terms of the license agreement you entered into with Eugene Eremeev (also |
| | 9 | | // known as Yevhenii Yeriemeieiv). |
| | 10 | | // -------------------------------------------------------------------------------- |
| | 11 | |
|
| | 12 | | namespace LeetCode.Algorithms.TwentyFourGame; |
| | 13 | |
|
| | 14 | | /// <inheritdoc /> |
| | 15 | | public class TwentyFourGameBruteForce : ITwentyFourGame |
| | 16 | | { |
| | 17 | | private const double TargetValue = 24.0; |
| | 18 | | private const double Tolerance = 1e-6; |
| | 19 | |
|
| | 20 | | /// <summary> |
| | 21 | | /// Time complexity - O(1) |
| | 22 | | /// Space complexity - O(1) |
| | 23 | | /// </summary> |
| | 24 | | /// <param name="cards"></param> |
| | 25 | | /// <returns></returns> |
| | 26 | | public bool JudgePoint24(int[] cards) |
| 3 | 27 | | { |
| 3 | 28 | | Array.Sort(cards); |
| | 29 | |
|
| 3 | 30 | | Span<bool> isCardUsed = stackalloc bool[4]; |
| 3 | 31 | | Span<int> cardPermutation = stackalloc int[4]; |
| | 32 | |
|
| 3 | 33 | | return TryBuildPermutation(0, cards, isCardUsed, cardPermutation); |
| 3 | 34 | | } |
| | 35 | |
|
| | 36 | | private static bool TryBuildPermutation(int depth, ReadOnlySpan<int> cards, Span<bool> isCardUsed, |
| | 37 | | Span<int> cardPermutation) |
| 82 | 38 | | { |
| 82 | 39 | | if (depth == 4) |
| 28 | 40 | | { |
| 28 | 41 | | return TryEvaluateAllExpressions(cardPermutation[0], cardPermutation[1], cardPermutation[2], |
| 28 | 42 | | cardPermutation[3]); |
| | 43 | | } |
| | 44 | |
|
| 54 | 45 | | var previousCard = -1; |
| | 46 | |
|
| 500 | 47 | | for (var i = 0; i < 4; i++) |
| 204 | 48 | | { |
| 204 | 49 | | if (isCardUsed[i]) |
| 119 | 50 | | { |
| 119 | 51 | | continue; |
| | 52 | | } |
| | 53 | |
|
| 85 | 54 | | if (cards[i] == previousCard) |
| 6 | 55 | | { |
| 6 | 56 | | continue; |
| | 57 | | } |
| | 58 | |
|
| 79 | 59 | | isCardUsed[i] = true; |
| 79 | 60 | | cardPermutation[depth] = cards[i]; |
| | 61 | |
|
| 79 | 62 | | if (TryBuildPermutation(depth + 1, cards, isCardUsed, cardPermutation)) |
| 8 | 63 | | { |
| 8 | 64 | | return true; |
| | 65 | | } |
| | 66 | |
|
| 71 | 67 | | isCardUsed[i] = false; |
| 71 | 68 | | previousCard = cards[i]; |
| 71 | 69 | | } |
| | 70 | |
|
| 46 | 71 | | return false; |
| 82 | 72 | | } |
| | 73 | |
|
| | 74 | | private static bool TryEvaluateAllExpressions(double a, double b, double c, double d) |
| 28 | 75 | | { |
| 300 | 76 | | foreach (var firstOperator in Enum.GetValues<Operation>()) |
| 109 | 77 | | { |
| 1191 | 78 | | foreach (var secondOperator in Enum.GetValues<Operation>()) |
| 433 | 79 | | { |
| 4757 | 80 | | foreach (var thirdOperator in Enum.GetValues<Operation>()) |
| 1730 | 81 | | { |
| 1730 | 82 | | if (TryApplyOperator(a, b, firstOperator, out var t) && |
| 1730 | 83 | | TryApplyOperator(t, c, secondOperator, out var u) && |
| 1730 | 84 | | TryApplyOperator(u, d, thirdOperator, out var v) && |
| 1730 | 85 | | Math.Abs(v - TargetValue) < Tolerance) |
| 1 | 86 | | { |
| 1 | 87 | | return true; |
| | 88 | | } |
| | 89 | |
|
| 1729 | 90 | | if (TryApplyOperator(b, c, secondOperator, out t) && |
| 1729 | 91 | | TryApplyOperator(a, t, firstOperator, out u) && |
| 1729 | 92 | | TryApplyOperator(u, d, thirdOperator, out v) && |
| 1729 | 93 | | Math.Abs(v - TargetValue) < Tolerance) |
| 0 | 94 | | { |
| 0 | 95 | | return true; |
| | 96 | | } |
| | 97 | |
|
| 1729 | 98 | | if (TryApplyOperator(b, c, secondOperator, out t) && |
| 1729 | 99 | | TryApplyOperator(t, d, thirdOperator, out u) && |
| 1729 | 100 | | TryApplyOperator(a, u, firstOperator, out v) && |
| 1729 | 101 | | Math.Abs(v - TargetValue) < Tolerance) |
| 0 | 102 | | { |
| 0 | 103 | | return true; |
| | 104 | | } |
| | 105 | |
|
| 1729 | 106 | | if (TryApplyOperator(c, d, thirdOperator, out t) && |
| 1729 | 107 | | TryApplyOperator(b, t, secondOperator, out u) && |
| 1729 | 108 | | TryApplyOperator(a, u, firstOperator, out v) && |
| 1729 | 109 | | Math.Abs(v - TargetValue) < Tolerance) |
| 1 | 110 | | { |
| 1 | 111 | | return true; |
| | 112 | | } |
| | 113 | |
|
| 1728 | 114 | | if (TryApplyOperator(a, b, firstOperator, out t) && |
| 1728 | 115 | | TryApplyOperator(c, d, thirdOperator, out u) && |
| 1728 | 116 | | TryApplyOperator(t, u, secondOperator, out v) && |
| 1728 | 117 | | Math.Abs(v - TargetValue) < Tolerance) |
| 0 | 118 | | { |
| 0 | 119 | | return true; |
| | 120 | | } |
| 1728 | 121 | | } |
| 431 | 122 | | } |
| 107 | 123 | | } |
| | 124 | |
|
| 26 | 125 | | return false; |
| 28 | 126 | | } |
| | 127 | |
|
| | 128 | | private static bool TryApplyOperator(double left, double right, Operation operation, out double result) |
| 25919 | 129 | | { |
| 25919 | 130 | | switch (operation) |
| | 131 | | { |
| | 132 | | case Operation.Addition: |
| 6547 | 133 | | result = left + right; |
| | 134 | |
|
| 6547 | 135 | | return true; |
| | 136 | | case Operation.Subtraction: |
| 6496 | 137 | | result = left - right; |
| | 138 | |
|
| 6496 | 139 | | return true; |
| | 140 | | case Operation.Multiplication: |
| 6462 | 141 | | result = left * right; |
| | 142 | |
|
| 6462 | 143 | | return true; |
| | 144 | | case Operation.Division: |
| 6414 | 145 | | if (Math.Abs(right) < Tolerance) |
| 46 | 146 | | { |
| 46 | 147 | | result = 0; |
| | 148 | |
|
| 46 | 149 | | return false; |
| | 150 | | } |
| | 151 | |
|
| 6368 | 152 | | result = left / right; |
| | 153 | |
|
| 6368 | 154 | | return true; |
| | 155 | | default: |
| 0 | 156 | | throw new ArgumentOutOfRangeException(nameof(operation), operation, null); |
| | 157 | | } |
| 25919 | 158 | | } |
| | 159 | |
|
| | 160 | | private enum Operation |
| | 161 | | { |
| | 162 | | Addition, |
| | 163 | | Subtraction, |
| | 164 | | Multiplication, |
| | 165 | | Division |
| | 166 | | } |
| | 167 | | } |