I am coding a blackjack game and I am very far through. However, I just got to the point of adding together the score after each hand (something I thought would be easy) but Aces are proving to rack my brain endlessly. Since casinos play with multiple decks, it's possible to get up to 21 aces in the same hand mathematically.
How do I make a loop to go through an ArrayList of Integers called Hand which has ints which correspond to the cards that are in the hand. EX. A player hits and now has a Ace, a 5, a 2, a King, and now draws an Ace. The arraylist to represent his hand is [1, 10, 2, 5, 1]
My idea:
public void calculatePlayerScore()
{
int counter = 0;
int aceCount = 0;
for (int i = 0; i < hand.size(); i++)
{
if (hand.get(i) != 1)
{
counter++;
}
else
{
aceCount++;
}
}
for (int i = 0; i < aceCount; i++)
{
//Now that we know the regular cards
//and we know how many aces there are
//we should be able to loop to find the most
//optimal score without busting, and pick the highest among those
}
If anyone has an idea for this, please let me know. Thanks so much for the help.
Note that only one ace can count as 11 in a hand. (Otherwise, the total will be at least 22.)
Calculate hand with all aces counting 1
if ( (hand total is <= 11) AND (there is at least one ace) )
hand total += 10 // one ace counts as 11
Only one ace can ever be 11. Summing a hand looks like this:
public int calculateScore(Hand hand) {
int total = 0;
bool hasAce = false;
for (int i = 0; i < hand.size(); i++) {
int r = hand.get(i);
total += r;
if (1 == r) { hasAce = true; }
}
if (hasAce && total < 12) { total += 10; }
return total;
}
In a real blackjack game, you might also want to return the fact of whether the hand total is soft or hard also.
IF the total of the hand is over 21 BUT one of the cards in the hand =11, then make 11 = 1.
Take the sum of your "Hand" ArrayList, for any location that you see an "Ace" at, calculate that sum with both 1 or 11 as the additive. If your sum is greater than 21, you bust. If not, continue. If it is exactly 21, add that hand to your successes, and stop hitting.
The brute force method of solving this problem is to implement a "look-ahead" function, where you can look at your entire hand once, then calculate all the possible combinations your hand provides, including the Aces within your hand as either 1's or 11's. After you generate this list of possibilities, you can then see which possibility has the least number of cards to create the blackjack or highest hand value, and choose that possibility. It's a common algorithm problem and there are probably very efficient solutions out there for you to look at.
Related
In my minimax algorithm, when the computer is presented with a player having two ways to win the computer then will just pick the first open position of the board. Take for example below. X can win in position 0,2 and position 1,0.
X | |
__________
| x |
__________
x | o | o
Currently my algorithm will place the o in the position 0,1. I believe it does this because as minimax runs and places an o in position 0,1 and because this is not a win, it calls minimax again, this time for x. X then moves in position 0,2 for a win. This returns -10 for this position. If the computer moves in position 0,2, minimax is called and x is eventually placed in position 1,0 which also returns a -10 for this move. In fact no matter where the computer places the o, -10 is returned since no matter what the player will win. Because for every position o is placed it returns -10, the computer places the o in the first available slot, which is 0,1 as max is never updated from the first position. I would like it to place the o in position 1,0 or 0,2 just to show that it recognizes a block.
My algorithm is below. It is for a 3x3x3 but the concept is the same.
public int MiniMax(int pGameState[][][], int Depth, boolean IsMax){
FunctionCalls++;
if(CheckForWin(2, pGameState)){ //Max Player (since the computer is always 2)
return 10 - Depth;
}
if(CheckForWin(1, pGameState)){ //Player will win therefore we return -10. If this is the first level of the tree
//then the value return is -10. If the second ply then the value returned is -8.
//It is more important for the computer to win sooner than later.
return -10 - Depth;
}
if(Depth >= 2){
return 0;
}
if(IsMax){
int Value = Integer.MIN_VALUE;
for(int i=0; i<3; i++){
for(int j=0; j<3; j++){
for(int k=0; k<3; k++){
if(pGameState[i][j][k] == 0){
pGameState[i][j][k] = 2;
int best = MiniMax(CopyArray(pGameState), Depth+1, !IsMax);
if(best > Value)
Value = best;
pGameState[i][j][k] = 0;
}
}
}
}
return Value;
}
else{
int Value = Integer.MAX_VALUE;
for(int i=0; i<3; i++){
for(int j=0; j<3; j++){
for(int k=0; k<3; k++){
if(pGameState[i][j][k] == 0){
pGameState[i][j][k] = 1;
int best = MiniMax(CopyArray(pGameState), Depth+1, !IsMax);
if(best < Value)
Value = best;
pGameState[i][j][k] = 0;
}
}
}
}
return Value;
}
}
I initially call minimax this way
best = MiniMax(CopyArray(GameState), 0, false);
I then compare best with my previous Max. If best is larger I save this move as my computer's move.
One simple way to deal with the first-available-move-chosen problem is to order the valid moves before iterating over them. Consider the position you described in the question:
X . .
. X .
X O O
Here O is to move. Before iterating over the board in the default way (left-to-right top-to-bottom), order the vector of four valid moves ((0, 1), (0, 2), (1, 0), (1, 2)) according to how good each move is. One way to do this is to use the evaluation function that will count how many threats each side has after the potential move is made. A threat for piece P (which can be X or O) is a row, column or diagonal that has one empty square and two P squares (so it's one piece P short from becoming a winning line). Let's see what this eval function will tell us for each of the four valid moves for the given position. We count number of threats for both pieces and assign to position the value S equal to the difference O_threats - X_threats.
If O makes a (0, 1) move, then O_threats = 0, X_threats = 2, so the score S = 0 - 2 = -2.
If O makes a (0, 2) move, then O_threats = 1, X_threats = 1, so the score S = 1 - 1 = 0.
If O makes a (1, 0) move, then O_threats = 0, X_threats = 1, so the score S = 0 - 1 = -1.
If O makes a (1, 2) move, then O_threats = 1, X_threats = 2, so the score S = 1 - 2 = -1.
Based on the calculated scores, the order of visiting the valid moves should be as follows: (0, 2), (1, 0), (1, 2), (0, 1). We know that all four moves are losing moves given the perfect play. And since their scores are equal (to the loss value -10), the first considered move (0, 2) won't be overwritten by the next ones. This will make the moves of the program "more intelligent", because it now respects the threats created/blocked by the move made (and threat considerations are often used by humans when playing tic-tac-toe). You can enforce different order of visiting the valid moves by using different evaluation function to sort them.
Also note that move ordering can be very useful for increasing the search depth when combined with alpha-beta pruning, because it allows to consider good valid moves first and increases the chance of pruning more nodes. Although alpha-beta pruning might be an overkill for a such simple game, it can be really useful for more complex games.
Here is one approach.
In the event of ties between multiple possible moves, calculate the expectimax, the move that gives you the highest probable score versus an opponent who plays randomly.
This will cause you to block one of the ways of winning in the hopes that the other doesn't see the best available move.
I got this interview question and I am still very confused about it.
The question was as the title suggest, i'll explain.
You are given a random creation function to use.
the function input is an integer n. let's say I call it with 3.
it should give me a permutation of the numbers from 1 - 3. so for example it will give me 2, 3 , 1.
after i call the function again, it won't give me the same permutation, now it will give me 1, 2, 3 for example.
Now if i will call it with n = 4. I may get 1,4,3,2.
Calling it with 3 again will not output 2,3,1 nor 1,2,3 as was outputed before, it will give me a different permutation out of the 3! possible permutations.
I was confused about this question there and I still am now. How is this possible within normal running time ? As I see it, there has to be some static variable that remembers what was called before or after the function finishes executing.
So my thought is creating a static hashtable (key,value) that gets the input as key and the value is an array of the length of the n!.
Then we use the random method to output a random instance out of these and move this instance to the back, so it will not be called again, thus keeping the output unique.
The space time complexity seems huge to me.
Am I missing something in this question ?
Jonathan Rosenne's answer was downvoted because it was link-only, but it is still the right answer in my opinion, being that this is such a well-known problem. You can also see a minimal explanation in wikipedia: https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order.
To address your space-complexity concern, generating permutations in lexicographical ordering has O(1) space complexity, you don't need to store nothing other than the current permutation. The algorithm is quite simple, but most of all, its correctness is quite intuitive. Imagine you had the set of all permutations and you order them lexicographically. Advancing to the next in order and then cycling back will give you the maximum cycle without repetitions. The problem with that is again the space-complexity, since you would need to store all possible permutations; the algorithm gives you a way to get the next permutation without storing anything. It may take a while to understand, but once I got it it was quite enlightening.
You can store a static variable as a seed for the next permutation
In this case, we can change which slot each number will be put in with an int (for example this is hard coded to sets of 4 numbers)
private static int seed = 0;
public static int[] generate()
{
//s is a copy of seed, and increment seed for the next generation
int s = seed++ & 0x7FFFFFFF; //ensure s is positive
int[] out = new int[4];
//place 4-2
for(int i = out.length; i > 1; i--)
{
int pos = s % i;
s /= i;
for(int j = 0; j < out.length; j++)
if(out[j] == 0)
if(pos-- == 0)
{
out[j] = i;
break;
}
}
//place 1 in the last spot open
for(int i = 0; i < out.length; i++)
if(out[i] == 0)
{
out[i] = 1;
break;
}
return out;
}
Here's a version that takes the size as an input, and uses a HashMap to store the seeds
private static Map<Integer, Integer> seeds = new HashMap<Integer, Integer>();
public static int[] generate(int size)
{
//s is a copy of seed, and increment seed for the next generation
int s = seeds.containsKey(size) ? seeds.get(size) : 0; //can replace 0 with a Math.random() call to seed randomly
seeds.put(size, s + 1);
s &= 0x7FFFFFFF; //ensure s is positive
int[] out = new int[size];
//place numbers 2+
for(int i = out.length; i > 1; i--)
{
int pos = s % i;
s /= i;
for(int j = 0; j < out.length; j++)
if(out[j] == 0)
if(pos-- == 0)
{
out[j] = i;
break;
}
}
//place 1 in the last spot open
for(int i = 0; i < out.length; i++)
if(out[i] == 0)
{
out[i] = 1;
break;
}
return out;
}
This method works because the seed stores the locations of each element to be placed
For size 4:
Get the lowest digit in base 4, since there are 4 slots remaining
Place a 4 in that slot
Shift the number to remove the data used (divide by 4)
Get the lowest digit in base 3, since there are 3 slots remaining
Place a 3 in that slot
Shift the number to remove the data used (divide by 3)
Get the lowest digit in base 2, since there are 2 slots remaining
Place a 2 in that slot
Shift the number to remove the data used (divide by 2)
There is only one slot remaining
Place a 1 in that slot
This method is expandable up to 12! for ints, 13! overflows, or 20! for longs (21! overflows)
If you need to use bigger numbers, you may be able to replace the seeds with BigIntegers
So I have a really basic coding question, I just started learning this year, and I have an assignment for a code that is supposed to
flip a fair coin n times and count how many heads it gets. The program will do m experiments and then
print out the results as a (vertical) histogram. The program will first ask the user to input the number of
experiments to perform (m) and the number of coin flips in each experiment (n). n can be at most 79. The
output will be a histogram made up of spaces and asterisks (*), with n+1 columns (for the number of heads
which can go from 0 to n)
I have the code for the histogram all done, but the problem I have is how to store the number of heads as it's own variable. For example, if it flipped the coin 80 times and 40 of them were heads, I would want it to create an int for 40 flips, then add one to it. I just don't know how to go about initializing 80 variables without writing out int one = 0; int two = 0, int three = 0; until the end of time, then writing 80 if statements until it finds the right integer to add one to. Is there an easy way to do this or should there be a different approach I should be taking? Here is the code, please be gentle, literally only a month or so into an extremely basic java class
for(m=m; m>0; m--) { //runs m number of experiments of n coinflips, keeping track of total heads
n = o; // when N gets set to 0 through the while loop, o resets it back to it's original so it can loop again
while(n>0) {
n--;
if(random.nextBoolean()) {
heads++;
total++;
/** here is where I want the number of heads saved to a
variable, so that way later I can run a loop to put as many *'s as I need in the histogram later */
Just use an array for the 80 (or n) experiments:
I don't understand, this would just count how many heads/tails there are right? This doesn't save them (ie it flipped 5 heads 6 times, 4 heads 3 times, 3 heads twice, ect) unless I'm misunderstanding
If you are storing the number of head m times (where m is < 80), you can:
1) print the histogram as you generate the results (no array needed) OR
2) store the 80 results in an array
Example for 1 (no array):
for(int x=0; x<experiments; x++){
int heads = 0;
for(int y=0; y<flips; y++){
if(rnd.nextInt(2) == 0) //assume 0 is head
heads ++;
}
//print histogram
for(int y=0; y<heads; y++)
System.out.print("*");
System.out.println();
}
Example for 2 (with array):
int[] expr = new int[80]; //store results for 80 experiments
for(int x=0; x<expriments; x++)
for(int y=0; y<flips; y++)
if(rnd.nextInt(2) == 0)
expr[x] ++;
Use an array:
int n = 80;
// space for n integers, with indexes 0..n
int[] histogram = new int[n + 1];
for (int i = 0; i < experiments; i++) {
// flip coin n times, counting heads
int heads = ...;
histogram[heads] = histogram[heads] + 1;
}
for (int i = 0; i < histogram.length; i++) {
printStars(histogram[i]);
}
If you're unfamiliar with arrays, the Java Tutorial has a good explanation.
Edit: It appears people are confusing this question for another. Both questions are about the same Foobar challenge. The other question asked for an approach better than the exponential time or omega(answer) brute force search, since a brute force search took too long. The answers there suggested using dynamic programming, which is a good idea that is much faster than a brute force search or backtracking, although not the best possible. This question starts with dynamic programming, which works on 4 out of 5 tests, but which seems to get the wrong answer for the 5th and perhaps largest test case. It doesn't take too long. It completes but gets the wrong answer. The answers to the other question do not help with this question, nor does the answer to this question help with that one, so they are not duplicates. They are about different aspects of the same task.
I am working on a Foobar Challenge, trying to determine the number of possible "Winning" roll combinations an individual could make using a 3-sided die. The simulated user will roll t times on a 1-dimensional "game-board" that is n spaces wide. The 3 sided die has 3 possible values: left (-1), stay (0), right (1). User starts out at location '0' on the board. If you are at 0 and you roll a -1 (left) then the game is invalid. If you are on the final square the only valid roll is 0 (stay). The objective is to determine the total amount of roll combinations a user could make that ends up with their marker being on the last square. (READ THE FULL CHALLENGE DESCRIPTION BELOW).
I have a semi-functioning solution to this challenge; however, when I submit it for review it fails 1 out of 5 test scenarios; problem is, Foobar doesn't disclose what the exact scenario was that failed, it simply says 'Test 5 failed!'. Would anybody be able to look at my Java code (below) and see what I am missing?
Here is my code:
public static int answer(int t, int n) {
if ((n - t) > 1) {
return 0;
}
if (n == 2) {
return t * 1;
}
if (t == n) {
return n;
}
// Use dynamic programming:
int lst[] = new int[n]; // lst[k] holds the # valid paths to position k using i-1 steps
int lst2[] = new int[n]; // put # valid paths to position k using i steps into lst2[k]
int total = 0;
lst[0] = 1;
lst[1] = 1;
int max = 1;
for (int i = 1; i < t; i++) {
lst2 = new int[n];
if (max < (n - 1)) {
max++;
}
for (int j = 0; j < n && j < (max + 1); j++) {
if (j == 0) {
lst2[j] = lst[j] + lst[j + 1];
} else if (j == max) {
if (j == (n - 1)) {
total += lst[j - 1];
} else {
lst2[j] = lst[j - 1];
}
} else {
lst2[j] = lst[j - 1] + lst[j] + lst[j + 1];
}
}
lst = lst2;
}
return total % 123454321;
}
Original Challenge Text
There you have it. Yet another pointless "bored" game created by the bored minions of Professor Boolean.
The game is a single player game, played on a board with n squares in a horizontal row. The minion places a token on the left-most square and rolls a special three-sided die.
If the die rolls a "Left", the minion moves the token to a square one space to the left of where it is currently. If there is no square to the left, the game is invalid, and you start again.
If the die rolls a "Stay", the token stays where it is.
If the die rolls a "Right", the minion moves the token to a square, one space to the right of where it is currently. If there is no square to the right, the game is invalid and you start again.
The aim is to roll the dice exactly t times, and be at the rightmost square on the last roll. If you land on the rightmost square before t rolls are done then the only valid dice roll is to roll a "Stay". If you roll anything else, the game is invalid (i.e., you cannot move left or right from the rightmost square).
To make it more interesting, the minions have leaderboards (one for each n,t pair) where each minion submits the game he just played: the sequence of dice rolls. If some minion has already submitted the exact same sequence, they cannot submit a new entry, so the entries in the leader-board correspond to unique games playable.
Since the minions refresh the leaderboards frequently on their mobile devices, as an infiltrating hacker, you are interested in knowing the maximum possible size a leaderboard can have.
Write a function answer(t, n), which given the number of dice rolls t, and the number of squares in the board n, returns the possible number of unique games modulo 123454321. i.e. if the total number is S, then return the remainder upon dividing S by 123454321, the remainder should be an integer between 0 and 123454320 (inclusive).
n and t will be positive integers, no more than 1000. n will be at least 2.
Languages
To provide a Python solution, edit solution.py To provide a Java solution, edit solution.java
Test cases
Inputs: (int) t = 1 (int) n = 2 Output: (int) 1
Inputs: (int) t = 3 (int) n = 2 Output: (int) 3
The counts grow exponentially in t. My guess is that the error is that you are overflowing the integer range. Reduce intermediate results mod m, or use a java.math.BigInteger.
Ok to make it simple yes there is a problem with int overflow. However you don't need to use a larger container ex BigInteger. All you need to store int the second array is the remainder ex lst2[j] = (lst[j - 1] + lst[j] + lst[j + 1]) % 123454321;. By doing this your value will never exceed 123454321 which will easily fit within an integer. then after every iteration of i use total %= 123454321; then you just need to return total. Since we are just adding paths moding the intermediate result just reduces it back to a manageable number.
I need help, I am trying to make use of Lattice Multiplication in java for use in a BigInt class I am having to write for a class.
Right now I have the code storing the digits needed for the adding part of the algorithm in a 2 dimensional array. From there though I am at a lose as to how to make a loop to go through the array and add the numbers in what would be a diagonal.
For instance here is the test numbers etc:
200
*311
= 62200
The array is holding:
6 0 0
2 0 0
2 0 0
6 is (2,2) in the array and the bottom right is (0,0)
I need to add in a diagonal, such as (1,0) + (0,1) = 0
The issue is how do I do this, since not only is it moving up and left in different ways, but it goes from 1 element to 2 elements to 3 elements, then back the other way, and of course this will get bigger the longer the number is.
This is the code that I have:
public int multiply(BigInt val){
int[] bigger;
int[] smaller;
int[] dStore;
int lengthMax = (val.getSize()+this.getSize()) - 1;
int first = 0;
int second = 0;
int[][] tempResult;
//Checks to see which is bigger and then adds that to bigger
if(val.getSize() >= this.getSize()){
bigger = val.getData();
smaller = this.getData();
dStore = new int[val.getSize()+this.getSize()];
}else{
bigger = this.getData();
smaller = val.getData();
dStore = new int[val.getSize()+this.getSize()];
}
tempResult = new int[smaller.length][bigger.length];
for(int i=0;i < smaller.length;i++){
for(int j = 0;j < bigger.length;j++){
tempResult[i][j] = smaller[i] * bigger[j];
}
}
** there is the return statement etc below
This might help as to explain lattice multi better: Lattice Multi Video
I would try a different approach. Look at the lattice in the video and imagine that you rotates the array a little bit to the left so that the diagonals becomes vertical. The array would then look like this:
2 3 5
8 3
2 4 0
Now, just summarize the columns and you would have the total.
You would of course have to split the numbers into arrays of digits first. The easiest way to do that (but not the most efficient) is to convert them into strings ...
Good luck!
To move diagonally, you'd increment both x and y:
// Loop though the diagonal of an array
x = 0;
y = 0;
while (x < ARR_X_SIZE && y < ARR_Y_SIZE) {
// Do something with arr[x][y]
x++;
y++;
}
This is the basic loop; you can change the x and y increments to determine the direction you need to go. The key to going through the whole array is the value of the coordinates going into the loop. Array:
1 2 3
4 5 6
7 8 9
If you set x = 1; y=0 at the beginning of the loop, you'll get 2 6. Set x = 0, y = 1 and you'll get 4 8.
I hope this helps you with your assignment. Good luck on the rest! That is definately an interesting algorithm to implement.