我正在执行以下编程练习:Can you win the codewar?。该语句是:

Two kingdoms are at war ⚔️ and, thanks to your codewarrior prowesses, you have been named general by one of the warring states. Your opponent's armies are larger than yours, but maybe you can reach a stalemate or even win the conflict if you are a good strategist.

You control the same number of armies as the rival state, but theirs are generally larger. You have to send a single army to fight each of your opponent's ones.
(It implies there will be as many battles as armies).
There are no possible David-and-Goliath surprises : the outcome of a battle is always the victory of the larger army (or a standoff if both are of the same size).
The winning side is the one which wins the most battles.
The outcome can be a stalemate if both win the same number.

You have to write a function

codewarResult(codewarrior, opponent)

that takes as input each side's armies as arrays of positive integers which represent their sizes. The function returns the strings "Defeat" , "Stalemate" or "Victory" depending on the outcome of the war for your side with an optimal strategy on your behalf.

For example, if you have 3 armies of sizes [1,4,1] and the rival state has armies of sizes [1,5,3] , despite you having on average smaller forces, it is possible to reach a stalemate :

1-1 : standoff
4-3 : victory for you
1-5 : victory for the opposing army

when the dust settles, you have won one battle, lost one, and one was indecisive so

codewarResult([1,4,1],[1,5,3])

should return "Stalemate".
More examples :

codewarResult([2,4,3,1],[4,5,1,2])

should return "Victory" because it is possible to win by disposing your amies this way :

2-1
4-4
3-2
1-5

thus winning two battles, deadlocking one and losing one.

codewarResult([1,2,2,1],[3,1,2,3])

should return "Defeat" because even with an optimal strategy it is not possible to win. The best you can do is one victory and one tie :

1-3
2-1
2-2
1-3


我尝试了以下算法:

import java.util.*;
public class Kata {
  public static String codewarResult(int[] codewarrior, int[] opponent) {
    System.out.println("codewarrior: "+Arrays.toString(codewarrior));
    System.out.println("opponent: "+Arrays.toString(opponent));

    List<Integer> opponentMatchedIndexes = new ArrayList<Integer>();
    int closestTo1 = Integer.MIN_VALUE;
    int indexInCodewarrior = 0;
    int indexInOpponent = 0;
    int score = 0;
    int battleResult = 0;

    for(int i = 0; i < codewarrior.length; i++){
      closestTo1 = Integer.MIN_VALUE;
      indexInCodewarrior = 0;
      indexInOpponent = 0;
      for(int j = 0; j < opponent.length; j++){
        battleResult = codewarrior[i]-opponent[j];
        if(!opponentMatchedIndexes.contains(j) && battleResult>closestTo1 && battleResult<=1){
          closestTo1 = battleResult;
          indexInCodewarrior = i;
          indexInOpponent = j;
        }
      }
      score+=closestTo1 < 0 ? -1 : closestTo1 == 0 ? 0 : 1;
      opponentMatchedIndexes.add(indexInOpponent);

      System.out.println("closesTo1: "+closestTo1);
      System.out.println("indexInCodewarrior: "+indexInCodewarrior);
      System.out.println("indexInOpponent: "+indexInOpponent);
      System.out.println("NumberInCodewarrior: "+codewarrior[indexInCodewarrior]);
      System.out.println("NumberInOpponent: "+opponent[indexInOpponent]);
      System.out.println("opponentMatchedIndexes: "+opponentMatchedIndexes);
      System.out.println("score: "+score);
    }

    return score<0?"Defeat":score==0?"Stalemate":"Victory";
  }
}


我们发现了一个测试,在应该输出“胜利”的情况下输出“僵局”:

@Test
public void testRandom() {
        int[] codewarrior = {2,5,1,4,1};
        int[] opponent =    {2,4,1,1,8};
    System.out.println(Arrays.toString(codewarrior)+" vs "+Arrays.toString(opponent));
    assertEquals("Victory", Kata.codewarResult(codewarrior, opponent));
}


我们已经写了应该做的代码:

2-1 = 1 --> score = 1; 5-4 = 1 --> score = 2; 1-1 = 0 --> score = 2; 4-2 = 2 --> score = 3; 1-8 = -7 --> score = 2


现在,我们键入了正在执行的代码:

2-1 = 1 --> score = 1; 5-4 = 1 --> score = 2; 1-1 = 0 --> score = 2; 4-8 = -4 --> score = 1; 1-8=-7 --> score = 0


正如您在第4步中注意到的那样,它应该做4-2 = 2->分数= 3;但是它确实是4-8 = -4->得分= 1。

我们已经确定了应该更改代码的那一行,并且我们也考虑了需要更改的内容,但是我们很难弄清楚我们到底需要多少更改!

特别是,我们需要更改以下代码行:

if(!opponentMatchedIndexes.contains(j) && battleResult>closestTo1 && battleResult<=1){


因为BattleResult 1,所以它只是跳过了将指令保存在if内的指令。

此外,我们已阅读:

Math.max and Math.min outputting highest and lowest values allowed
get closest value to a number in array

此外,我们如何调试较大的测试?我的意思是,以下测试也失败了,但是由于输入数组的大小较大,因此很难弄清发生了什么:

@Test
public void testNumerousArmies() {
        int[] codewarrior = {2,1,3,1,1,3,3,2,3,1,1,1,3,1,3,1,3,3,1,2,3,3,1,3};
        int[] opponent =    {4,4,1,4,3,1,4,4,3,2,1,2,1,3,3,1,4,4,3,2,3,2,4,1};
    System.out.println(Arrays.toString(codewarrior)+" vs "+Arrays.toString(opponent));
    assertEquals("Stalemate", Kata.codewarResult(codewarrior, opponent));
}


如果您感到好奇,则完整的测试套件为:

import java.util.Arrays;
import org.junit.Test;
import static org.junit.Assert.assertEquals;

// TODO: Replace examples and use TDD development by writing your own tests

public class SolutionTest {
    @Test
    public void testStalemate() {
            int[] codewarrior = {1,4,1};
            int[] opponent =    {1,5,3};
        System.out.println(Arrays.toString(codewarrior)+" vs "+Arrays.toString(opponent));
        assertEquals("Stalemate", Kata.codewarResult(codewarrior, opponent));
    }

    @Test
    public void testVictory() {
            int[] codewarrior = {2,4,3,1};
            int[] opponent =    {4,5,1,2};
        System.out.println(Arrays.toString(codewarrior)+" vs "+Arrays.toString(opponent));
        assertEquals("Victory", Kata.codewarResult(codewarrior, opponent));
    }

    @Test
    public void testDefeat() {
            int[] codewarrior = {1,2,2,1};
            int[] opponent =    {3,1,2,3};
        System.out.println(Arrays.toString(codewarrior)+" vs "+Arrays.toString(opponent));
        assertEquals("Defeat", Kata.codewarResult(codewarrior, opponent));
    }

    @Test
    public void testEqualArmies() {
            int[] codewarrior = {1,1,1,1};
            int[] opponent =    {1,1,1,1};
        System.out.println(Arrays.toString(codewarrior)+" vs "+Arrays.toString(opponent));
        assertEquals("Stalemate", Kata.codewarResult(codewarrior, opponent));
    }

    @Test
    public void testSingleArmy() {
            int[] codewarrior = {5};
            int[] opponent =    {6};
        System.out.println(Arrays.toString(codewarrior)+" vs "+Arrays.toString(opponent));
        assertEquals("Defeat", Kata.codewarResult(codewarrior, opponent));
    }

    @Test
    public void testNumerousArmies() {
            int[] codewarrior = {2,1,3,1,1,3,3,2,3,1,1,1,3,1,3,1,3,3,1,2,3,3,1,3};
            int[] opponent =    {4,4,1,4,3,1,4,4,3,2,1,2,1,3,3,1,4,4,3,2,3,2,4,1};
        System.out.println(Arrays.toString(codewarrior)+" vs "+Arrays.toString(opponent));
        assertEquals("Stalemate", Kata.codewarResult(codewarrior, opponent));
    }


    @Test
    public void testRandom() {
            int[] codewarrior = {2,5,1,4,1};
            int[] opponent =    {2,4,1,1,8};
        System.out.println(Arrays.toString(codewarrior)+" vs "+Arrays.toString(opponent));
        assertEquals("Victory", Kata.codewarResult(codewarrior, opponent));
    }
}


我们如何编写最佳策略来配对两个给定数组的对,并赢得大多数比较?

最佳答案

首先,您需要根据战斗强度对阵列进行排序。从最高的开始比较。


如果您无法赢得战斗,那么您将以最低的实力来抵抗它。
如果这是一个僵局。您现在有2个选项。让它成为僵局,或放松争取他人的战斗。因此,现在您将更深入地测试结果,以查看您赢得最多的地方。


例:

codewarChallenge([2,4,3,1],[4,5,1,2])

按以下顺序放置它们:([1,2,3,4],[1,2,4,5])

4-5,您将放松,因此玩1-5。现在您已经离开([2,3,4],[1,2,4])

4-4对峙。两个选项4-4或2-4。

当您玩4-4时,您剩下([2,3],[1,2]),您将同时赢得

当您玩2-4时,您剩下([3,4],[1,2]),您将同时赢得

所以4-4是更好的选择。

您将需要使用递归模式。使一个函数接受两个数组并给出分数作为返回值。 0表示损失,1表示对峙,2表示获胜。现在在遇到僵局时递归调用该函数,以获取两个选项的其余分数。最高分获胜。

关于java - 配对两个给定阵列的对并赢得大多数比较的最佳策略,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60360729/

10-08 21:46