I need a bit of help with a project, I want to create a java program that creates a kind of histogram in the shape of triangles, its hard to explain so look at the following example
input : 3 1 12 0 7
output:
_
/|\
/ | \
/ | \
/ | \
/ | \ _
/ | \ /|\
/ | \ / | \
/ | \ / | \
_ / | \ / | \
/|\ / | \ / | \
/ | \ _ / | \ / | \
/ | \ /|\ / | \ _ / | \
<=======><===><=========================><=><===============>
| | | | | | | | |
in my code I've managed to create the input part, and the generator of the base, but the triangles/piramides generator doesnt make the correct spaces, anyone can help me?
here is my code to make the triangles (assuming the input is what is in the array numbers and numbers2):
public class Spires{
public static void main(String[] args){
int[] numbers = {3,1,12,0,7};
int counter = 6, max = 12;
int[] numbers2 = {3,1,12,0,7};
for(int row = max+1; row >= 0; --row) {
System.out.println();
for(int col = 0; col < counter-1; ++col) {
if(numbers2[col] >= row){
for(int spacesleft = 1; spacesleft < (numbers2[col] + col)+row-1; ++spacesleft){
System.out.print(" ");
}
if(numbers2[col] != row){
System.out.print("/");
for(int c3 = 0; c3 < numbers2[col]-row-1; ++c3) {
System.out.print(" ");
}
System.out.print("|");
for(int c3 = 0; c3 < numbers2[col]-row-1; ++c3) {
System.out.print(" ");
}
System.out.print("\\");
}else{
System.out.print("_");
}
// for(int spacesright = 1; spacesright < numbers2[col] + col + row -1; ++spacesright){
// System.out.print(" ");
// }
}
}
}
System.out.println();
//base generator
for(int i = 0; i<counter-1; ++i) {
System.out.print("<");
for(int i2 = 0; i2 < 2*numbers[i]+1; ++i2) {
System.out.print("=");
}
System.out.print(">");
}
System.out.println();
for(int i = 0; i<counter-1; ++i) {
if(numbers[i] != 0){
System.out.print(" |");
for(int i2 = 0; i2 < 2*numbers[i]-1; ++i2) {
System.out.print(" ");
}
System.out.print("| ");
}else{
System.out.print(" | ");
}
}
}
}
My output comes out like this:
_
/|\
/ | \
/ | \
/ | \
/ | \ _
/ | \ /|\
/ | \ / | \
/ | \ / | \
_ / | \ / | \
/|\ / | \ / | \
/ | \ _ / | \ / | \
/ | \/|\ / | \ _ / | \
<=======><===><=========================><=><===============>
| | | | | | | | |
I need some help figuring out how to add the missing spaces and remove some
You're almost there! Just a couple tweaks that need to be made.
The calculation for number of outside spaces on the left and right side of the triangle legs is actually very simple: row + 1. Because each triangle is being built from the bottom up, triangles shown on row 0 (bottom row) need 1 space, row 1 need 2 spaces, etc.
If the current row is "above" the triangle column you are displaying, you still need to output spaces to mark a placeholder for that triangle. So the if (numbers2[col] >= row) needs a corresponding else to display spaces instead.
Applying these two changes gets something like:
if(numbers2[col] >= row){
// corrected calculation \-------/
for(int spacesleft = 0; spacesleft < row + 1; ++spacesleft){
System.out.print(" ");
}
if(numbers2[col] != row){
System.out.print("/");
for(int c3 = 0; c3 < numbers2[col] - row - 1; ++c3) {
System.out.print(" ");
}
System.out.print("|");
for(int c3 = 0; c3 < numbers2[col] - row - 1; ++c3) {
System.out.print(" ");
}
System.out.print("\\");
}else{
System.out.print("_");
}
// corrected calculation \-------/
for(int spacesright = 0; spacesright < row + 1; ++spacesright){
System.out.print(" ");
}
// output spaces to fill area for that column and shift everything over properly
} else {
for (int spaces = 0; spaces < numbers2[col] * 2 + 3; spaces++)
System.out.print(" ");
}
This should output the histogram as expected.
Now I'd like you to consider why this code is challenging to work with. There is a direct relationship to the number of variables and ideas you have to hold in your head at once, to the difficulty of reading and understanding a piece of code.
One way you could make this code easier to reason about is by breaking it up into different functions that handle different aspects of the problem individually. For example, we might add methods for:
printing a certain number of spaces
printing one row of a triangle
Also it helps to use more variables with intuitive names, so you don't have to keep reasoning through the entire calculations. Here is an example that should demonstrate:
// output 'count' spaces
public static void printSpaces(int count) {
for (int spaces = 0; spaces < count; spaces++) System.out.print(" ");
}
// output one row of a triangle based on supplied height
// and current display row, starting at 0=top row.
public static void printTriangleSection(int triangleHeight, int rowOfTriangle) {
int triangleWidth = triangleHeight * 2 + 3; // total width taken up by this triangle
int halfWidth = triangleHeight + 1; // total width taken up by one side (excluding the middle)
int spacesOutside = halfWidth - rowOfTriangle; // total spaces outside of triangle hypotenuse
int spacesInside = rowOfTriangle - 1; // total spaces inside triangle hypotenuse
if (rowOfTriangle < 0) { // above the first row of the triangle
printSpaces(triangleWidth);
} else if (rowOfTriangle == 0) {
printSpaces(spacesOutside);
System.out.print("_");
printSpaces(spacesOutside);
} else {
printSpaces(spacesOutside);
System.out.print("/");
printSpaces(spacesInside);
System.out.print("|");
printSpaces(spacesInside);
System.out.print("\\");
printSpaces(spacesOutside);
}
}
Then the relevant part of your main method would simplify to this:
for(int row = max+1; row >= 0; --row) {
System.out.println();
for(int col = 0; col < counter-1; ++col) {
printTriangleSection(numbers2[col], numbers2[col] - row);
}
}
Introduction
The reason that I'm providing this answer is to write about how to reason through a coding problem. The triangle histogram was interesting enough for me to work out a solution.
Here's one test run:
Enter the heights of the triangles: 3 1 12 0 7
-
/|\
/ | \
/ | \
/ | \
/ | \ -
/ | \ /|\
/ | \ / | \
/ | \ / | \
- / | \ / | \
/|\ / | \ / | \
/ | \ - / | \ / | \
/ | \ /|\ / | \ - / | \
<=======><===><=========================><=><===============>
| | | | | | | | |
Enter the heights of the triangles:
Reasoning
The heights of the triangles are input, and the histogram triangles are output. Pressing the Enter key without typing any numbers lets the program know to exit.
When I looked at the histogram, I noticed 3 things.
I could create a Java class to form the triangle, and create an instance of the class for each triangle I needed to draw. In the example test run, I create 5 triangles, so I create 5 instances of the class.
If I create the base row first, I can use positioning of the < and > signs to calculate where to start the triangle sides.
The histogram is much easier to create from the bottom up than from the top down.
Now, it helps a lot that I know I can use a StringBuilder to create a blank string and place characters within the blank string using the setCharAt method. This way, I don't have to calculate the number of blanks in between and in the middle of the triangles.
It also helps a lot that I know I can use a List to store the output strings, and print them in the reverse order of their creation.
So, here' the first hint I can give you for solving coding problems.
If something seems real hard to accomplish, ask someone if there's an easier way.
There may not be an easier way. Some coding problems are that hard. But sometimes, you may not be aware of an easier solution.
So, here's the code that produces the histogram.
package com.ggl.testing;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class TriangleHistogram implements Runnable {
public static void main(String[] args) {
new TriangleHistogram().run();
}
#Override
public void run() {
Scanner scanner = new Scanner(System.in);
List<TriangleModel> triangleHistogram = readInput(scanner);
while (triangleHistogram.size() > 0) {
String baseString = createBaseString(triangleHistogram);
String bottomString = createBottomString(triangleHistogram,
baseString.length());
List<String> histogramStrings = new ArrayList<>();
histogramStrings.add(bottomString);
histogramStrings.add(baseString);
createTriangleStrings(triangleHistogram, histogramStrings);
displayHistogram(histogramStrings);
triangleHistogram = readInput(scanner);
}
scanner.close();
}
private List<TriangleModel> readInput(Scanner scanner) {
List<TriangleModel> triangleHistogram = new ArrayList<>();
System.out.print("Enter the heights of the triangles: ");
String inputLine = scanner.nextLine();
if (!inputLine.trim().isEmpty()) {
String[] triangleSizes = inputLine.split("\\s");
for (int i = 0; i < triangleSizes.length; i++) {
TriangleModel triangleModel = new TriangleModel(
Integer.parseInt(triangleSizes[i]));
triangleHistogram.add(triangleModel);
}
}
return triangleHistogram;
}
private String createBaseString(List<TriangleModel> triangleHistogram) {
StringBuilder builder = new StringBuilder();
for (TriangleModel triangleModel : triangleHistogram) {
triangleModel.setColumns(builder);
triangleModel.createBase(builder);
}
return builder.toString();
}
private String createBottomString(List<TriangleModel> triangleHistogram,
int length) {
StringBuilder builder = createStringBuilder(' ', length);
for (TriangleModel triangleModel : triangleHistogram) {
triangleModel.createBottom(builder);
}
return builder.toString();
}
private void createTriangleStrings(List<TriangleModel> triangleHistogram,
List<String> histogramStrings) {
String histogramString = "";
do {
String baseString = histogramStrings.get(1);
StringBuilder builder = createStringBuilder(' ',
baseString.length());
for (TriangleModel triangleModel : triangleHistogram) {
triangleModel.createTriangle(builder);
}
histogramString = builder.toString();
histogramStrings.add(histogramString);
} while (!histogramString.trim().isEmpty());
}
private StringBuilder createStringBuilder(char c, int length) {
StringBuilder builder = new StringBuilder(length);
for (int i = 0; i < length; i++) {
builder.append(c);
}
return builder;
}
private void displayHistogram(List<String> histogramStrings) {
for (int i = histogramStrings.size() - 1; i >= 0; i--) {
String line = histogramStrings.get(i);
System.out.println(line);
}
System.out.println();
}
public class TriangleModel {
private final int height;
private int leftColumn;
private int centerColumn;
private int rightColumn;
public TriangleModel(int height) {
this.height = height;
}
public void setColumns(StringBuilder builder) {
this.leftColumn = builder.length() + 1;
this.centerColumn = leftColumn + height;
this.rightColumn = centerColumn + height;
}
public void createBase(StringBuilder builder) {
builder.append('<');
for (int i = 0; i < getBaseWidth(); i++) {
builder.append('=');
}
builder.append('>');
}
public void createBottom(StringBuilder builder) {
builder.setCharAt(leftColumn, '|');
builder.setCharAt(rightColumn, '|');
}
public void createTriangle(StringBuilder builder) {
if (leftColumn < rightColumn) {
builder.setCharAt(leftColumn, '/');
builder.setCharAt(centerColumn, '|');
builder.setCharAt(rightColumn, '\\');
leftColumn++;
rightColumn--;
} else if (leftColumn == rightColumn) {
builder.setCharAt(centerColumn, '-');
leftColumn++;
rightColumn--;
}
}
private int getBaseWidth() {
return height + height + 1;
}
}
}
Explanation
I made the main TringleHistogram class implement Runnable so that I could put the main code in the run method. I don't like to put a lot of code in the constructor of the class.
The run method is a synopsis of what happens in the code. I get the heights from the user, and I create the histogram. I create the base line first, then the bottom line, then the triangles in reverse order.
The while loop in the run method uses a priming read. I call the readInput method once before the while loop and once again at the end of the while loop. That way, I don't have to skip any part of the while loop when the user just presses the Enter key.
The readInput method doesn't do any error checking. Error checking could be added in the readInput method.
I broke up the code in the TriangleHistogram class into multiple methods. Each method does what the name of the method says it does. Naming methods is important to do descriptively. Generally, I use a verb - noun construction.
The TriangleModel class draws a triangle. Looking in the class, there's not much math involved. As I create the base line, I set the columns of the left center, and right parts of the triangle. As I create each line of the histogram, I adjust the left and right columns until they meet at the top of the triangle.
You can see in the TriangleModel methods that placing characters on a blank StringBuilder is much simpler than appending blanks and characters.
Development
I didn't write the entire program in one shot. I wrote small pieces of the program and tested them. The advantage to writing a little and testing a little is that when you find a problem, you have a good idea where in the code the problem lies.
I wrote the readInput method and enough of the run method to exercise the while loop. I wrote just enough of the TriangleModel class to hold the height. The program didn't do anything but process the input, create a List of TriangleModel objects, and not crash. The not crashing part was the most important.
I added the rest of the fields to the TriangleModel class and created the base line of the histogram. Finally, some output I could look at! Yay!
I created the bottom line of the histogram. This allowed me to veriy that the left column and right column of the triangle were defined correctly.
I created one line above the base of the histogram. This allowed me to verify the center column of the triangle was defined correctly and the List of output strings was created and printed in reverse order.
I wrote the rest of the code. This is where my program crashed first. I forgot to adjust the left and right columns when they were equal. I found the problem quickly because I knew the problem was in the new code.
Then I was done. I spent some time cleaning up some of the code and making field names and method names more descriptive.
You can learn these techniques for writing code. Here's the last hint I can give you.
You're not writing code for a compiler. You're writing code so that other people, including yourself 3 months later, can read and easily understand the code.
Start with broad ideas, and dive into more and more detail as you move further down the code.
I hope this answer is helpful.
Related
I'm solving a challenge about making an algorithm.
There is a game of land.
The Land of Landing game consists of 4 rows in total N rows, with scores in all the columns.
When stepping down from the first row, down one row, you must step down on one of the four squares of each row.
However, there is a special rule that can not be repeated in the same row when landing one row at a time.
For example,
| 1 | 2 | 3 | 5 |
| 5 | 6 | 7 | 8 |
| 4 | 3 | 2 | 1 |
If you have stepped on line 1 through line 4 (5), you can not step on line 4 (8) on line 2.
I was trying to use Dynamic Programming in Java.
import java.lang.Math;
import java.util.*;
class Solution {
int [][] dp = new int[100001][4];
int solution(int[][] land) {
int r = land.length;
for (int i = 0; i < 4; i++)
{
dp[0][i] = land[0][i];
}
for (int i = 0; i <r; i++)
{
for (int j = 0; j < 4; ++j)
{
for(int k = 0; k < 4; ++k)
{
if (j != k)
{
dp[i][j] = Math.max(dp[i][j], land[i][j] + dp[i-1][k]);
}
}
}
}
int ans = 0;
for (int i = 0; i < 4; ++i)
{
ans = Math.max(ans, dp[r-1][i]);
}
return ans;
}
}
it shows error
java.lang.ArrayIndexOutOfBoundsException: -1
I was thinking that it was probably something wrong with the Conditional statement.
In C++, these conditional statements are right. It's running perfect. Why am I getting an error in Java? Is there any difference using array between Java and C++?
Can you please tell me how can I solve this error?
dp[i-1][k] - i starts from ZERO in upper loop, so results of this expression becomes -1 as index.
Java array index starts from ZERO, not -1, which is why ArrayIndexOutOfBoundsException.
I don't know the business case, but one way to solve this is, start first for loop from 1 instead 0.
I write to solve a Codility problem provided below,
You are going to build a stone wall. The wall should be straight and N meters long, and its thickness should be constant; however, it should have different heights in different places. The height of the wall is specified by an array H of N positive integers. H[I] is the height of the wall from I to I+1 meters to the right of its left end. In particular, H[0] is the height of the wall's left end and H[N−1] is the height of the wall's right end.
The wall should be built of cuboid stone blocks (that is, all sides of such blocks are rectangular). Your task is to compute the minimum number of blocks needed to build the wall.
Write a function:
class Solution { public int solution(int[] H); }
that, given an array H of N positive integers specifying the height of the wall, returns the minimum number of blocks needed to build it.
For example, given array H containing N = 9 integers:
H[0] = 8 H[1] = 8 H[2] = 5
H[3] = 7 H[4] = 9 H[5] = 8
H[6] = 7 H[7] = 4 H[8] = 8
the function should return 7. The figure shows one possible arrangement of seven blocks.
Assume that:
N is an integer within the range [1..100,000];
each element of array H is an integer within the range [1..1,000,000,000].
Complexity:
expected worst-case time complexity is O(N);
expected worst-case space complexity is O(N) (not counting the storage required for input arguments).
I write a solution for the provided problem. The algorithm and code is provided below,
Algorithm
i. set block count = 1 and start iterating from the 2nd element of the array
ii. if the current depth is same as previous, keep going
iii. If the current depth is higher, push that in the stack and increase the count
iv. If the current depth is lower, keep poping till the current depth >= peek. Afterward, if the stack size = 0 or higher, increase the block count by 1
The code,
public static int solution(int[] H) {
Stack<Integer> stack = new Stack<>();
stack.push(H[0]);
int count = 1;
int N = H.length;
for (int i = 1; i < N; i++) {
if (H[i] == stack.peek()) {
continue;
} else if (H[i] > stack.peek()) {
stack.push(H[i]);
count++;
} else {
while (!stack.isEmpty() && H[i] < stack.peek()) {
stack.pop();
}
stack.push(H[i]);
count++;
}
}
return count;
}
The solution doesn't provide the correct answer and I can't find the bug even after spending some time in debugging. Can anyone see that?
The test set is provided below and the answer is 7 (I get 8).
int[] H = new int[9];
H[0] = 8;
H[1] = 8;
H[2] = 5;
H[3] = 7;
H[4] = 9;
H[5] = 8;
H[6] = 7;
H[7] = 4;
H[8] = 8;
Thank you.
Python Solution
Here is my solution
Solution with steps details
Codility python 100%
def solution(H):
"""
Codility 100%
https://app.codility.com/demo/results/trainingQKD6JP-PHA/
Idea is to use stack concept
Compute the minimum number of blocks needed to build the wall.
To build the wall start taking blocks of height one by one.
We need to take care of -
- the blocked should not be used again
- this is done only up to blocks height is greater than current
- why we are using last 8 height block if there is already 8 height block used in previous step?
reason is 8 is not present in stack top
8,
8,----- can not use because on stack top 8 is already there
5,
7,
9,
8,
7,------ can not use because on stack top 7 is already there
4,
8,
This is just example with height, see steps of output for details
skip8 skip7
| |
| | | |
| | | | |
| | | | |
| | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
Used blocks-
8
5
7
9
8
4
8
"""
block_count = 0
# stack is used to hold height used to building and remove all the blocks from it,
# if any of the block of stack is greater than current block(to be added for building)
stack = []
for height in H:
print(" ")
print("Current Height " + str(height))
print("Current stack " + str(stack))
# Remove all blocks that are bigger than current height, stack should not be empty
while stack and stack[-1] > height:
stack.pop()
print("After remove bigger blocks than current height " + str(stack))
# stack is not empty and top item of stack is equal to current height
if stack and stack[-1] == height:
# Already used this size of block
print("Already used this size of block " + str(height))
continue
else:
# new block is required, push it's size to the stack
block_count += 1
stack.append(height)
print("Add this block.... " + str(height) + " Minimum Blocks " + str(block_count))
return block_count
Another one in Java. Simpler, because I used assumption that height > 0.
public int solution(int[] hs) {
int squares = 0;
Stack<Integer> s = new Stack<>();
s.push(0);
for (int h: hs) {
while (s.peek() > h) {
s.pop();
}
if (s.peek() != h) {
s.push(h);
++squares;
}
}
return squares;
}
I find the bug and though it may be good to share. The reason is the new height is lesser than the peek value, we will keep popping the entities. So if the stack is not empty, the new height will be the same or higher than the stack peeks value.
If the new height will be the same, it means we already add a block for the height and will not add a new block. A condition is needed for the situation,
if (!stack.isEmpty() && H[i] == stack.peek()) {
continue;
}
The code is provided below provides 100% score,
public int solution(int[] H) {
Stack<Integer> stack = new Stack<>();
stack.push(H[0]);
int count = 1;
int N = H.length;
for (int i = 1; i < N; i++) {
if (H[i] == stack.peek()) {
continue;
} else if (H[i] > stack.peek()) {
stack.push(H[i]);
count++;
} else {
while (!stack.isEmpty() && H[i] < stack.peek()) {
stack.pop();
}
/*
* the new entity is either in same elevation or higher
* */
/*
* if in same elevation, we already added the block, so keep iterating
* */
if (!stack.isEmpty() && H[i] == stack.peek()) {
continue;
}
stack.push(H[i]);
count++;
}
}
return count;
}
If someone is still interested in this exercise, I share my Python solution (100% in Codility)
def solution(H):
stack, count = [], 1
for i in H:
if stack:
if i == stack[-1]:
continue
if i < stack[-1]:
while stack and stack[-1] > i:
stack.pop()
if stack:
if i > stack[-1]:
count+=1
stack.append(i)
else:
count+=1
stack.append(i)
else:
stack.append(i)
return count
Ruby 100%
def solution(h)
h.inject([1, [h.first]]) do |(blocks, stack), n|
next [blocks+1, stack.push(n)] if stack.last < n
stack.pop while stack.any? && stack.last > n
next [blocks, stack] if stack.last == n
[blocks+1, stack.push(n)]
end.first
end
A simpler java solution.
public int solution(int[] H) {
//block count
int count = 0;
// stack is used to hold height used to building and remove all the blocks from it,
// if any of the block of stack is greater than current block(is to be added for building)
Deque<Integer> stack = new ArrayDeque<>();
for (int a : H) {
// Remove all blocks that are bigger than current height, stack should not be empty
while (!stack.isEmpty() && a < stack.peek()) {
stack.pop();
}
//new block is required, push it's size to the stack
if (stack.isEmpty() || a > stack.peek()) {
count++;
stack.push(a);
}
}
return count;
}
My 100% JavaScript solution with O(N) time complexity:
function solution(H) {
let numBlocks = 0;
const blocksHeights = [0];
for (const height of H) {
while (blocksHeights[blocksHeights.length - 1] > height) {
blocksHeights.pop();
}
if (blocksHeights[blocksHeights.length - 1] !== height) {
blocksHeights.push(height);
numBlocks++;
}
}
return numBlocks;
}
in c# (100% in Codility)
public int solution(int[] H) {
Stack<int> stack = new Stack<int>();
stack.Push(H[0]);
int count = 1;
for (int i = 1; i < H.Length; i++)
{
if (H[i] == stack.Peek())
{
continue;
}
else if (H[i] > stack.Peek())
{
stack.Push(H[i]);
count++;
}
else
{
while (!(stack.Count==0) && H[i] < stack.Peek())
{
stack.Pop();
}
if (!(stack.Count==0) && H[i] == stack.Peek()) {
continue;
}
stack.Push(H[i]);
count++;
}
}
return count;
}
100% C++ in Codility
#include <stack>
int solution(vector<int> &H) {
int cnt{0};
std::stack<int> reusedStone;
for (auto h : H) {
if (reusedStone.empty() || (h > reusedStone.top())) {
reusedStone.push(h); cnt++;
} else if (h < reusedStone.top()) {
while ((!reusedStone.empty()) && (h < reusedStone.top())) {
reusedStone.pop();
}
if ((!reusedStone.empty()) && (h == reusedStone.top())) {
continue;
} else {
reusedStone.push(h); cnt++;
}
}
}
return cnt;
}
My python solution (100% success rate on Codility)
import math
def solution(H):
nb_blocks = 0
horizon = [math.inf]
for h in H:
while horizon and h < horizon[-1]:
horizon.pop()
if (horizon and h > horizon[-1]) or (not horizon):
horizon.append(h)
nb_blocks += 1
return nb_blocks
I was trying to get a grasp of MiniMax algorithm, and have read up on it. My initial approach was to implement a simple MiniMax algorithm, and then to add alpha-beta pruning. However this is my current code:
public int miniMax(char[] node, int playerNum)
{
int victor = checkWin(node); // returns 0 if game is ongoing, 1 for p1, 2 for p2, 3 for tie.
if(victor != 0) //game over .
return score(victor);
if(playerNum == 2) //AI
{
int bestVal = Integer.MIN_VALUE;
int bestSpot = 0;
for(int i = 0; i < node.length; i++)
{
if(node[i] != '-')
continue;
node[i] = getSymbol(playerNum);
int value = miniMax(node, 1);
if(value > bestVal)
{
bestVal = value;
bestSpot = i;
}
node[i] = '-';
}
return bestSpot;
}
else
{
int bestVal = Integer.MAX_VALUE;
int bestSpot = 0;
for(int i = 0; i < node.length; i++)
{
if(node[i] != '-')
continue;
node[i] = getSymbol(playerNum);
int value = miniMax(node, 2);
if(value < bestVal)
{
bestVal = value;
bestSpot = i;
}
node[i] = '-';
}
return bestSpot;
}
}
And my score function
private int Score(int gameState)
{
if(gameState ==2) //O wins.
return 10;
else if(gameState==1) //X wins
return -10;
return 0;
}
Now, I have a working AI that tries to block my move and win, however sometimes it is making non-intelligent choices for instance this is the output I get if my input read from console is 6,7,8 in that order. It does not attempt to block my win. But in other cases it does.
| O | O | |
| | | |
| X | X | X |
In my second attempt I tried 4,3 and it blocked my winning move.
| | O | |
| X | X | O |
| | | |
I was wondering anyone could point out what is wrong with my implementation?
The behavior of the code for the shown examples is correct!
So why is the threat in the following position not blocked? Why does the program play move 1 instead of 6?
O . . O 1 2
. . . numbering available moves: 3 4 5
X X . X X 6
It is because if the game is lost on perfect play the program just plays the first available move.
The algorithm only cares about win or loss and not in how many moves.
See what happens if the threat is blocked:
O . . O . .
. . . . X . and X wins on his next move
X X O X X O
I'm trying to build a sudoku solver. I know my code is messy and there will probably be a much simpler way to do it, but I would like finish the algorithm the way I started.
The algorithm starts doing what I want (filling the blank spaces with the first number that could fit), but when it reaches a point with no options, I don't know how to go back and erase the last number I inserted to try with another combination. But I can't just erase the last number from the matrix because it could be a number that wasn't placed by the algorithm.
If someone could help I would really appreciate it.
public class Backtracking{
public static void Sudoku(int[][] sudokuTable){
if (isAnswer(sudokuTable)){
printSudoku(sudokuTable);
}else{
for (int j = 1; j <=9; j++){
if (canfit(sudokuTable, j)){
addToSudoku(sudokuTable, j);
printSudoku(sudokuTable);
Sudoku(sudokuTable);
}
}
}
}
public static void addToSudoku(int[][] sudokuTable, int n){
int i = 0;
int j = 0;
boolean done = false;
while (i < 9 && !done){
while (j < 9 && !done){
if (sudokuTable[i][j] == 0){
sudokuTable[i][j] = n;
done = true;
}
j++;
}
i++;
}
}
public static void printSudoku(int[][] sudokuTable){
for (int i = 0; i < 9; i++){
for (int j = 0; j < 9; j++){
System.out.print(sudokuTable[i][j] + " ");
}
System.out.println();
}
System.out.println();
}
public static boolean isAnswer(int[][] sudokuTable){
int sum = 0;
for (int i = 0; i < 9; i++){
for (int j = 0 ; j < 9; j++){
if (sudokuTable[i][j] > 9 || sudokuTable[i][j] < 1)
return false;
else
sum++;
}
}
if (sum != 405)
return false;
return true;
}
public static boolean canfit(int[][] sudokuTable, int n){
int i = 0;
int j = 0;
boolean pos = false;
boolean fit = true;
while (i < 9 && !pos){
while (j < 9 && !pos){
if (sudokuTable[i][j] == 0)
pos = true;
else
j++;
}
if (!pos)
i++;
}
for (int k = 0; k < 9; k++){
if (sudokuTable[i][k] == n && k != j)
fit = false;
}
if (fit){
for (int l = 0; l < 9; l++){
if(sudokuTable[l][j] == n && l != i)
fit = false;
}
}
if (fit){
if (i >= 0 && i < 3)
i = 0;
else if (i >=3 && i < 6)
i = 3;
else if (i >=6 && i < 9)
i = 6;
if (j >= 0 && j < 3)
j = 0;
else if (j >=3 && j < 6)
j = 3;
else if (j >=6 && j < 9)
j = 6;
for (int m = i; m < i+3; m++){
for (int o = j; o < j+3; o++){
if (sudokuTable[m][o] == n)
fit = false;
}
}
}
return fit;
}
Try to return true or false from your Sudoko method.
when isAnswer() method returns true, print table. Then return true from Sudoko() method.
Now inside your for loop, where you are calling Sudoko() method recursively, check if it returns true, or false. If it returns true, that means your choice is correct and it leads to a solution, you need not to do anything else. If it returns false, remove the number you set using addToSudoko() method. Make the table as it was before calling addToSudoko() method and continue iterating.
And if your for loop, loops for 9 times and none of the number has a suitable spot, that means if loop ends, return false.
Hope this helps
Actually you can backtracking moves by using an array, each time a move is wrong you just start to remove some moves and try a different move, however this has a problem:
the complexity of trying all possible moves is huge (how long does it takes to try all digits on a number with 81 digits? even if you cut computation time here and there , you will need all the time of the universe)
the main problem in sudoku is that you have no clue which was the wrong move if you move randomly.
Assume the following case sudoky with 2x2 cells:
+----+----++-----+-----+
| 1 | 2 || 3 | 4 |
+----+----++-----+-----+
| 4 | 3 || 1 | 2 |
+====+====++=====+=====+
| 2 | 1 || 4 | 3 |
+----+----++-----+-----+
| 3 | 4 || 2 | 1 |
+----+----++-----+-----+
If you use your algorithm in the following (unsolved) case:
+----+----++-----+-----+
| 1 | || | 4 |
+----+----++-----+-----+
| | || | |
+====+====++=====+=====+
| 2 | || | |
+----+----++-----+-----+
| | 4 || | 1 |
+----+----++-----+-----+
it is possible he will run into the following sequence
+----+----++-----+-----+
| 1 | || 2 | 4 |
+----+----++-----+-----+
| | || 2 | |
+====+====++=====+=====+
| 2 | || | |
+----+----++-----+-----+
| | 4 || | 1 |
+----+----++-----+-----+
Actually the added "twos" are both wrong, but when your algorithm find that those are wrong because you have 2 "twos" in the same column, you don't know which one was the wrong one (the first added, the second added, or both?)
A correct backtracking algorithm would works like this:
You start with a 81 cells arrays, and you start placing numbers (in sequence).
.
for(int i=0; i<81; i++)
array[i] = TryNumber();
.
then you check after each added number if that was correct.
.
if(SomeNumberNotCorrect())
break; // you know you can stop "tryingnumbers" so you can save on loop executions
.
But you don't know which was the wrong number
Now writing a correct algorithm that solves sudokus by attemps and do not run in million of years is pretty long and I cannot write it here but I don't think the way you choosen is the best. The best way is to apply the same strategies used by players. Just keep in mind that if you want an algorithm to resolve sudokus in a similiar way to how Chess is played by computer your algorithm would require much more time than a Chess game (infact a computer cannot analize chess moves more than 5-6 turns). But infact Sudokus can be resolved with much faster algorithms.
Instead I've already done in past a simple solver you could actually try to apply the same strategies a player would use to solve it:
In example:
For each cell, check if current Sector, Column and Line have already all numbers except 1, then you can add that number. And to check that for each cells you just need 81*81*81 moves.
When your solver do not find anymore solutions on a Sudoku, it is just because you have to develop as player a new strategy and then you need to apply it to your program, in short you will have a program that will be able to solve every sudoku (not very hard, and actually this is the reason that there are a lot of free sudoku solvers out there).
| * |
| * |
| * |
| * |
| * |
| * |
| * |
| * |
| * |
| * |
| * |
| * |
|* |
I need to print something like the above ASCII plot for a Gambler's Ruin problem. Where the stake & goal are taken as args. The left most | represents 0 dollars, the right most | represents the goal and the * represents the cash on hand. My program is below:
public class RuinPath {
public static void main(String[] args) {
// TODO - Your solution
int stake = Integer.parseInt(args[0]); // gambler's stating bankroll
int goal = Integer.parseInt(args[1]); // gambler's desired bankroll
{
int i = 0;
if (i == 0) {
System.out.print("|");
i++;
while (i < stake) {
System.out.print(" ");
i++;
if (i == stake) {
System.out.print("*");
i++;
while (i > stake && i < goal) {
System.out.print(" ");
i++;
if (i == goal) {
System.out.print("|");
i = 0;
System.out.println();
{
if (Math.random() < 0.5) {
stake++; // win $1
} else {
stake--; // lose $1
}
if (stake == 1 || stake == goal - 1);
break;
}
}
}
}
}
}
}
}
}
what this program prints though is:
| * |
* |
* |
* |
* |
* |
* |
* |
* |
* |
* |
* |
* |
* |
*
Why does my program not loop so that i can get the left most | to appear to represent 0 dollars all the way through? I have it so i = 0; at the end of the loop so that when it goes back around it should re-loop until the stake is 1 or less than the goal. Instead it re-loops from the middle of the program.
Your logic is a little too complicated. Also, your indentation will make any sort of debugging extremely difficult.
Just take it one step at a time:
public class RuinPath {
public static void main(String[] args) {
int stake = Integer.parseInt(args[0]); // Starting bankroll
int goal = Integer.parseInt(args[1]); // Desired bankroll
while (stake > 0 && stake < goal) {
System.out.print("|");
// Print out the spaces. Using a for loop and
// printing a "*" if the counter variable
// is equal to stake is good way to do it.
// Flip a coin and increment/decrement the stake
System.out.print("|\n");
}
}
}
Here is a broken out solution that might be easier to reason about:
import java.io.PrintStream;
public class SO {
private static int gambleWithCaution(int stake) {
if (Math.random() < 0.5) {
return stake+1; // win $1
} else {
return stake-1; // lose $1
}
}
private static void renderStanding(int stake, int goal) {
System.out.print('|');
for(int dollar = 1; dollar< goal; dollar++) {
if(dollar == stake) {
System.out.print('*');
} else {
System.out.print(' ');
}
}
System.out.println('|');
}
public static void main(String ... args) {
int stake = Integer.parseInt(args[0]); // gambler's stating bankroll
int goal = Integer.parseInt(args[1]); // gambler's desired bankroll
while(stake > 0 && stake < goal) {
renderStanding(stake, goal);
stake = gambleWithCaution(stake);
}
System.out.println((stake > goal) ? "You Won!" : "You Lost");
}
}
With the values 3 and 5 you get this output:
| * |
| * |
|* |
| * |
| * |
| *|
| * |
| *|
You Won!
Now that this is seperated out you can have some fun with it like creating a gamble function like this:
private static int gambleWithReclessAbandon(int stake, int goal, double abandon) {
int onTheLine = (int)(Math.random() * (int)(stake * abandon));
if(stake < (0.5)*goal) {
//If you are at less than 50% of your goal then just put it all on the line
//and let it ride :)
onTheLine = stake;
}
if (Math.random() < 0.5) {
return stake+onTheLine; // win $
} else {
return stake-onTheLine; // lose $
}
}
Which can be invoked like this:
//Gamble up to 80% of your current stake
stake = gambleWithReclessAbandon(stake, goal, 0.80);
With the same two values this is what I saw on my first pass (I was sooo close :)):
| * |
| * |
| *|
| * |
| *|
You Lost