| | | 1 | | // -------------------------------------------------------------------------------- |
| | | 2 | | // Copyright (C) 2026 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 sealed 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 | | } |