我正在执行以下编程练习: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/