I am building a math game for java and I'm stuck at this part as per the details of my assignment. The rules are simple: you have to use each number only once and only the 4 numbers that were read from the user to find one equation to obtain 24.
For example, for the numbers 4,7,8,8, a possible solution is: (7-(8/8))*4=24.
Most sets of 4 digits can be used in multiple equations that result in 24. For example the input 2,2,4,7 can be used in multiple ways to obtain 24:
2+2*(4+7) = 24
2+2*(7+4) = 24
(2+2)*7-4 = 24
(2*2)*7-4 = 24
2*(2*7)-4 = 24
There are also combinations of 4 numbers that cannot result into any equation equal with 24. For example 1,1,1,1. In this case, your program should return that there is no possible equation equal with 24.
Note: Although we will enter 4 integers between 1 and 9, we will use doubles to compute all the operations. For example, the numbers 3,3,8,8 can be combined into the formula: 8/(3-8/3) = 24.
Workflow: Your program should read the 4 numbers from the user and output a formula that results in 24. The algorithm should enumerate all the possible orders of 4 numbers, all the possible combinations and all the possible formulas.
Which leads me to 24 permutations of Numbers a,b,c,d and 64 permutations of operators +-/*. How I came to this conclusion was 4^3 4 operators only 3 fill spots in the equation. Except today I am having trouble writing the evaluation method and also accounting for parentases in the equations.
Here is my code:
public static void evaluate(cbar [][] operations , double [][] operands)
{
/*
This is the part that gets me how am I supposed to account
for parentases and bring all these expressions togather to
actually form and equation.
*/
}
This problem presents several challenges. My solution below is about two hundred lines long. It's probably a little longer than the assignment requires because I generalized it to any number of terms. I encourage you to study the algorithm and write your own solution.
The main obstacles we must overcome are the following.
How do we generate permutations without repetition?
How do we build and evaluate arithmetic expressions?
How do we convert the expressions into unique strings?
There are many ways to generate permutations. I chose a recursive approach because it's easy to understand. The main complication is that terms can be repeated, which means that there may be fewer than 4! = 4*3*2*1 permutations. For example, if the terms are 1 1 1 2, there are only four permutations.
To avoid duplicating permutations, we start by sorting the terms. The recursive function finds places for all duplicate terms from left to right without backtracking. For example, once the first 1 has been placed in the array, all the remaining 1 terms are placed to the right of it. But when we get to a 2 term, we can go back to the beginning of the array.
To build arithmetic expressions, we use another recursive function. This function looks at each position between two terms of the permutation, splitting the array into a segment to the left of the position and a segment to the right. It makes a pair of recursive calls to build expressions for the left and right segments. Finally, it joins the resulting child expressions with each of the four arithmetic operators. The base case is when the array is of size one, so it can't be split. This results in a node with no operator and no children, only a value.
Evaluating the expressions by performing arithmetic on double values would be problematic due to the imprecision of floating-point division. For example, 1.0 / 3 = 0.33333..., but 3 * 0.33333... = 0.99999.... This makes it difficult to know for sure that 1 / 3 * 3 = 1 when you're using double values. To avoid these difficulties, I defined a Fraction class. It performs arithmetic operations on fractions and always simplifies the result by means of the greatest common divisor. Division by zero does not result in an error message. Instead, we store the fraction 0/0.
The final piece of the puzzle is converting expressions into strings. We want to make canonical or normalized strings so that we don't repeat ourselves needlessly. For example, we don't want to display 1 + (1 + (1 + 2)) and ((1 + 1) + 1) + 2, since these are essentially the same expression. Instead of showing all possible parenthesizations, we just want to display 1 + 1 + 1 + 2.
We can achieve this by adding parentheses only when necessary. To wit, parentheses are necessary if a node with a higher-priority operator (multiplication or division) is the parent of a node with a lower-priority operator (addition or subtraction). By priority I mean operator precedence, also known as the order of operations. The higher-priority operators bind more tightly than the lower ones. So if a parent node has higher priority than the operator of a child node, it is necessary to parenthesize the child. To ensure that we end up with unique strings, we check them against a hash set before adding them to the result list.
The following program, Equation.java, accepts user input on the command line. The parameters of the game are on the first line of the Equation class. You can modify these to build expressions with more terms, bigger terms, and different target values.
import java.lang.*;
import java.util.*;
import java.io.*;
class Fraction { // Avoids floating-point trouble.
int num, denom;
static int gcd(int a, int b) { // Greatest common divisor.
while (b != 0) {
int t = b;
b = a % b;
a = t;
}
return a;
}
Fraction(int num, int denom) { // Makes a simplified fraction.
if (denom == 0) { // Division by zero results in
this.num = this.denom = 0; // the fraction 0/0. We do not
} else { // throw an error.
int x = Fraction.gcd(num, denom);
this.num = num / x;
this.denom = denom / x;
}
}
Fraction plus(Fraction other) {
return new Fraction(this.num * other.denom + other.num * this.denom,
this.denom * other.denom);
}
Fraction minus(Fraction other) {
return this.plus(new Fraction(-other.num, other.denom));
}
Fraction times(Fraction other) {
return new Fraction(this.num * other.num, this.denom * other.denom);
}
Fraction divide(Fraction other) {
return new Fraction(this.num * other.denom, this.denom * other.num);
}
public String toString() { // Omits the denominator if possible.
if (denom == 1) {
return ""+num;
}
return num+"/"+denom;
}
}
class Expression { // A tree node containing a value and
Fraction value; // optionally an operator and its
String operator; // operands.
Expression left, right;
static int level(String operator) {
if (operator.compareTo("+") == 0 || operator.compareTo("-") == 0) {
return 0; // Returns the priority of evaluation,
} // also known as operator precedence
return 1; // or the order of operations.
}
Expression(int x) { // Simplest case: a whole number.
value = new Fraction(x, 1);
}
Expression(Expression left, String operator, Expression right) {
if (operator == "+") {
value = left.value.plus(right.value);
} else if (operator == "-") {
value = left.value.minus(right.value);
} else if (operator == "*") {
value = left.value.times(right.value);
} else if (operator == "/") {
value = left.value.divide(right.value);
}
this.operator = operator;
this.left = left;
this.right = right;
}
public String toString() { // Returns a normalized expression,
if (operator == null) { // inserting parentheses only where
return value.toString(); // necessary to avoid ambiguity.
}
int level = Expression.level(operator);
String a = left.toString(), aOp = left.operator,
b = right.toString(), bOp = right.operator;
if (aOp != null && Expression.level(aOp) < level) {
a = "("+a+")"; // Parenthesize the child only if its
} // priority is lower than the parent's.
if (bOp != null && Expression.level(bOp) < level) {
b = "("+b+")";
}
return a + " " + operator + " " + b;
}
}
public class Equation {
// These are the parameters of the game.
static int need = 4, min = 1, max = 9, target = 24;
int[] terms, permutation;
boolean[] used;
ArrayList<String> wins = new ArrayList<String>();
Set<String> winSet = new HashSet<String>();
String[] operators = {"+", "-", "*", "/"};
// Recursively break up the terms into left and right
// portions, joining them with one of the four operators.
ArrayList<Expression> make(int left, int right) {
ArrayList<Expression> result = new ArrayList<Expression>();
if (left+1 == right) {
result.add(new Expression(permutation[left]));
} else {
for (int i = left+1; i < right; ++i) {
ArrayList<Expression> leftSide = make(left, i);
ArrayList<Expression> rightSide = make(i, right);
for (int j = 0; j < leftSide.size(); ++j) {
for (int k = 0; k < rightSide.size(); ++k) {
for (int p = 0; p < operators.length; ++p) {
result.add(new Expression(leftSide.get(j),
operators[p],
rightSide.get(k)));
}
}
}
}
}
return result;
}
// Given a permutation of terms, form all possible arithmetic
// expressions. Inspect the results and save those that
// have the target value.
void formulate() {
ArrayList<Expression> expressions = make(0, terms.length);
for (int i = 0; i < expressions.size(); ++i) {
Expression expression = expressions.get(i);
Fraction value = expression.value;
if (value.num == target && value.denom == 1) {
String s = expressions.get(i).toString();
if (!winSet.contains(s)) {// Check to see if an expression
wins.add(s); // with the same normalized string
winSet.add(s); // representation was saved earlier.
}
}
}
}
// Permutes terms without duplication. Requires the terms to
// be sorted. Notice how we check the next term to see if
// it's the same. If it is, we don't return to the beginning
// of the array.
void permute(int termIx, int pos) {
if (pos == terms.length) {
return;
}
if (!used[pos]) {
permutation[pos] = terms[termIx];
if (termIx+1 == terms.length) {
formulate();
} else {
used[pos] = true;
if (terms[termIx+1] == terms[termIx]) {
permute(termIx+1, pos+1);
} else {
permute(termIx+1, 0);
}
used[pos] = false;
}
}
permute(termIx, pos+1);
}
// Start the permutation process, count the end results, display them.
void solve(int[] terms) {
this.terms = terms; // We must sort the terms in order for
Arrays.sort(terms); // the permute() function to work.
permutation = new int[terms.length];
used = new boolean[terms.length];
permute(0, 0);
if (wins.size() == 0) {
System.out.println("There are no feasible expressions.");
} else if (wins.size() == 1) {
System.out.println("There is one feasible expression:");
} else {
System.out.println("There are "+wins.size()+" feasible expressions:");
}
for (int i = 0; i < wins.size(); ++i) {
System.out.println(wins.get(i) + " = " + target);
}
}
// Get user input from the command line and check its validity.
public static void main(String[] args) {
if (args.length != need) {
System.out.println("must specify "+need+" digits");
return;
}
int digits[] = new int[need];
for (int i = 0; i < need; ++i) {
try {
digits[i] = Integer.parseInt(args[i]);
} catch (NumberFormatException e) {
System.out.println("\""+args[i]+"\" is not an integer");
return;
}
if (digits[i] < min || digits[i] > max) {
System.out.println(digits[i]+" is outside the range ["+
min+", "+max+"]");
return;
}
}
(new Equation()).solve(digits);
}
}
I would recommend you to use a tree structure to store the equation, i.e. a syntactic tree in which the root represents and operator having two children representing the operands and so on recursively. You would probably get a cleaner code doing it like that, because then you won't need to generate the combinations of operands "by hand", but you can make a code which picks every operand from a 1-dimensional char[] operands = new char[] {'+','-','*','/'} array.
If you don't want to use a syntactic tree or think it's not necessary for your use case you can always try to find a different way to make the code to pick operands from the 1-dimensional array and store them into a different data structure. But I would especially avoid writing all the combinations as you are doing. It does not look very easy to maintain.
I have fixed the similar puzzle with below code.
public static boolean game24Points(int[] operands) {
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine engine = sem.getEngineByName("javascript");
char[] operations = new char[] { '+', '-', '*', '/' };
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
for (int k = 0; k < 4; k++) {
try {
String exp = "" + operands[0] + operations[i] + operands[1] + operations[j]
+ operands[2] + operations[k] + operands[3];
String res = engine.eval(exp).toString();
if (Double.valueOf(res).intValue() == 24) {
System.out.println(exp);
return true;
}
} catch (ScriptException e) {
return false;
}
}
}
}
return false;
}
Here are testcases
public void testCase01() {
int[] operands = { 7, 2, 1, 10 };
assertEquals(true, Demo.game24Points(operands));
}
public void testCase02() {
int[] operands = { 1, 2, 3, 4 };
assertEquals(true, Demo.game24Points(operands));
}
public void testCase03() {
int[] operands1 = { 5, 7, 12, 12 };
assertEquals(true, Demo.game24Points(operands1));
int[] operands = { 10, 3, 3, 23 };
assertEquals(true, Demo.game24Points(operands));
}
Related
So here is the thing.
I have to write code to show a binary number X's next smallest "code-X number" which is bigger than binary number X.
code-X number is a binary number which have no continuously 1. For example: 1100 is not a code X number because it has 11, and 1001001001 is a code-X number
Here is my code
String a = "11001110101010";
String b = "";
int d = 0;
for(int i = a.length()-1; i>0;i--){
if(a.charAt(i) == '1' && a.charAt(i-1)=='1'){
while(a.charAt(i)=='1'){
b = b + '0';
if(i!=0){i--;}
d++;
}
}
b = b + a.charAt(i);
}
StringBuffer c = new StringBuffer(b);
System.out.println(c.reverse());
I plan on copy the binary string to string b, replace every '1' which next i is '1' into '0' and insert an '1'
like:
1100 ---> 10000
but i have no idea how to do it :)
May you help me some how? Thanks
Try this. This handles arbitrary length bit strings. The algorithm is as follows.
Needed to conditionally modify last two bits to force a change if the number is not a codeEx number. This ensures it will be higher. Thanks to John Mitchell for this observation.
Starting from the left, find the first group of 1's. e.g 0110
If not at the beginning replace it with 100 to get 1000
Otherwise, insert 1 at the beginning.
In all cases, replace everything to the right of the grouping with 0's.
String x = "10000101000000000001000001000000001111000000000000110000000000011011";
System.out.println(x.length());
String result = codeX(x);
System.out.println(x);
System.out.println(result);
public static String codeX(String bitStr) {
StringBuilder sb = new StringBuilder(bitStr);
int i = 0;
int len = sb.length();
// Make adjust to ensure new number is larger than
// original. If the word ends in 00 or 10, then adding one will
// increase the value in all cases. If it ends in 01
// then replacing with 10 will do the same. Once done
// the algorithm takes over to find the next CodeX number.
if (s.equals("01")) {
sb.replace(len - 2, len, "10");
} else {
sb.replace(len- 1, len, "1");
}
while ((i = sb.indexOf("11")) >= 0) {
sb.replace(i, len, "0".repeat(len - i));
if (i != 0) {
sb.replace(i - 1, i + 2, "100");
} else {
sb.insert(i, "1");
}
}
String str = sb.toString();
i = str.indexOf("1");
return i >= 0 ? str.substring(i) : str;
}
Prints
10000101000000000001000001000000001111000000000000110000000000011011
10000101000000000001000001000000010000000000000000000000000000000000
Using raw binary you can use the following.
public static void main(String[] args) {
long l = 0b1000010100000000010000010000000011110000000000110000000000011011L;
System.out.println(
Long.toBinaryString(nextX(l)));
}
public static long nextX(long l) {
long l2 = l >>> 1;
long next = Long.highestOneBit(l & l2);
long cutoff = next << 1;
long mask = ~(cutoff - 1);
return (l & mask) | cutoff;
}
prints
1000010100000000010000010000000010000000000000000000000000000000
EDIT: Based on #WJS correct way to find the smallest value just larger.
This is a slight expansion WJS' 99% correct answer.
There is just one thing missing, the number is not incremented if there are no consecutive 1's in the original X string.
This modification to the main method handles that.
Edit; Added an else {}. Starting from the end of the string, all digits should be inverted until a 0 is found. Then we change it to a 1 and break before passing the resulting string to WJS' codeX function.
(codeX version does not include sb.replace(len-2,len,"11");)
public static void main(String[] args) {
String x = "10100";
StringBuilder sb = new StringBuilder(x);
if (!x.contains("11")) {
for (int i = sb.length()-1; i >= 0; i--) {
if (sb.charAt(i) == '0') {
sb.setCharAt(i, '1');
break;
} else {
sb.setCharAt(i, '0');
}
}
}
String result = codeX(sb.toString());
System.out.println(x);
System.out.println(result);
}
Problem statement: Sherlock and the Valid String
This code passes all tests for correctness, 15/20, however, some tests are failing because of the time limits.
What are good practices about making code faster? How can for loops be avoided?
static String isValid(String s) {
String yesOrNo;
//Step 1: count the frequency of each char and out in a map <char, number>
Map<Character, Integer> map = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
int count = 0;
for (int c = 0; c < s.length(); c++) {
if (s.charAt(c) == s.charAt(i))
count++;
}
map.put(s.charAt(i), count);
}
//Step2: add all the numbers of occurrences of each char into a list
List<Integer> values = new ArrayList<>();
for (Map.Entry<Character, Integer> kv : map.entrySet()
) {
values.add(kv.getValue());
}
//Step 3: find the benchmark number
Map<Integer, Integer> occurPairs = new TreeMap<>();
for (int i = 0; i < values.size(); i++) {
occurPairs.put(values.get(i), Collections.frequency(values, values.get(i)));
}
Map.Entry<Integer, Integer> popVal = Collections.max(occurPairs.entrySet(), Map.Entry.comparingByValue());
Map.Entry<Integer, Integer> smallest = Collections.min(occurPairs.entrySet(), Map.Entry.comparingByValue());
//Step 4: compare each value with the benchmark
int numOfWrong = 0;
for (Integer value : values) {
if (!value.equals(popVal.getKey()))
numOfWrong += Math.abs(popVal.getKey() - value);
}
if (occurPairs.size() == 2 && smallest.getValue() == 1 && smallest.getKey() == 1)
yesOrNo = "YES";
else if (numOfWrong > 1)
yesOrNo = "NO";
else
yesOrNo = "YES";
System.out.println(yesOrNo);
return yesOrNo;
}
I won't tell you outright what's wrong but I'll give you a conceptual framework by which you can analyze your code.
Think about the number of steps you perform per letter in the input string.
If you perform a fixed number of steps then you'll get linear scaling. Let's say you do three steps per letter. If there are n letters and you perform 3n operations, you're in good shape.
However, if you perform n operations per letter then you'll get quadratic scaling with n² or 3n² or operations in total. (The constant in front is not important. It's the exponent that matters.) Let's say you have 1,000 letters. 3n scaling would mean 3 thousand operations. 3n² scaling would mean 3 million.
Quadratic basically means "doesn't scale". Instead of scaling in proportion to the input length, quadratic algorithms blow up when the input gets large. They work fine for normal workloads but fall apart when under pressure. Hacker Rank is very likely throwing really long input strings at your algorithm to detect quadratic blowup.
I talked about n above. In Java lingo n is s.length(). Can you spot the quadratic step in your code where you are performing s.length() * s.length() operations?
Yes, in step 1 I'm iterating twice over the s to count the frequency of each char.
That's right. Good. Now, how could you do step 1 in a single pass?
Think about how you'd do it on paper. You wouldn't scan the string over and over and over and over and over, right? You'd just look at each letter once and keep a running count of all the letters as you go. You'd probably have a table with letters and tally marks like:
A ||||
B
C |
D ||
E |||||||
F
...
Do the same in code and it'll cut the n² down to n.
In addition to #JohnKugelman answer, here is what you can do.
First of all, you are going through your string twice (with inner loop) to count the occurrences which is O(n^2). You already found a O(n) solution for that
Map<Character, Integer> occurences = new HashMap<>();
s.chars()
.forEach(e-> occurences.put((char)e, occurences.getOrDefault((char)e, 0) + 1));
Now we need to find a simple iteration to find out the answer.
Here are what we know about the "YES" cases.
All of the letters have same frequency e.g: aabbccddeeff
All of the letters have same frequency but a single letter which occurs 1 time more. e.g: aabbccddd
All of the letters have same frequency but a single letter with 1 occurrence. e.g: aaaabbbbcccce
So what we need to do is to go through values of our map and count the number of occurrences.
First, let's get our iterator
Iterator<Map.Entry<Character, Integer>> iterator = occurences
.entrySet()
.iterator();
Then choose first number as "benchmark" and define a variable and a count for first different value
int benchmark = iterator.next().getValue();
int benchmarkCount = 1;
int firstDifferent = -1;
int differentCount = 0;
Iterate through the numbers
while(iterator.hasNext()) {
int next = iterator.next().getValue();
if (next == benchmark) { // if the next number is same
benchmarkCount++; // just update our count
} else { // if it is different
// if we haven't found a different one yet or it is the same different value from earlier
if (firstDifferent == -1 || firstDifferent == next) {
firstDifferent = next;
differentCount++;
}
}
}
Now all we need to do is to analyze our numbers
int size = occurences.size();
if (benchmarkCount == size) return "YES"; // if all of the numbers are the same
if (benchmarkCount == size - 1) { // if we hit only single different
// either the diffent number is 1 or it is greater than our benchmark by value of 1
if (firstDifferent == 1 || firstDifferent - benchmark == 1) {
return "YES";
}
}
// same case with above
if (differentCount == size - 1) {
if (benchmark == 1 || benchmark - firstDifferent == 1) {
return "YES";
}
}
Full solution
static String isValid(String s) {
Map<Character, Integer> occurences = new HashMap<>();
s.chars().forEach(e-> occurences.put((char)e, occurences.getOrDefault((char)e, 0) + 1));
Iterator<Map.Entry<Character, Integer>> iterator = occurences
.entrySet()
.iterator();
int benchmark = iterator.next().getValue();
int benchmarkCount = 1;
int firstDifferent = -1;
int differentCount = 0;
while(iterator.hasNext()) {
int next = iterator.next().getValue();
if (next == benchmark) {
benchmarkCount++;
} else {
if (firstDifferent == -1 || firstDifferent == next) {
firstDifferent = next;
differentCount++;
}
}
}
int size = occurences.size();
if (benchmarkCount == size) return "YES";
if (benchmarkCount == size - 1) {
if (firstDifferent == 1 || firstDifferent - benchmark == 1) {
return "YES";
}
}
if (differentCount == size - 1) {
if (benchmark == 1 || benchmark - firstDifferent== 1) {
return "YES";
}
}
return "NO";
}
I find the other solutions far too complicated. Using the number of different characters (counts.length below) and their minimum frequency (min below), we know that the string length is at least counts.length * min.
When a single character occurs once more than min, we have a string longer by one.
When there are more such characters, the string gets longer than counts.length * min + 1. When any character occurs even more often than min + 1, the string gets longer than counts.length * min + 1, too.
As noted by Bunyamin Coskuner, my solution missed cases like "aabbc". This one works but it's no more as simple as wanted:
static String isValid(String s) {
if (s.isEmpty()) return "YES";
final int[] counts = s.chars()
.mapToObj(c -> c)
.collect(Collectors.groupingBy(c -> c, Collectors.counting()))
.values()
.stream()
.mapToInt(n -> n.intValue())
.toArray();
final int min = Arrays.stream(counts).min().getAsInt();
// Accounts for strings like "aabb" and "aabbb".
if (s.length() <= counts.length * min + 1) return "YES";
// Here, strings can be only valid when the minimum is one, like for "aabbc".
if (min != 1) return "NO";
final int minButOne = Arrays.stream(counts).filter(n -> n>1).min().getAsInt();
return s.length() == (counts.length - 1) * minButOne + 1 ? "YES" : "NO";
}
I am trying to add two binary numbers and then get their sum in binary system. I got their sum in decimal and now I am trying to turn it into binary. But there is problem that when I take their sum (in decimal) and divide by 2 and find remainders(in while loop), I need to put remainders into array in order print its reverse. However, there is an error in array part. Do you have any suggestions with my code? Thanks in advance.
Here is my code:
import java.util.Scanner;
public class ex1 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int m = scan.nextInt();
int k = dec1(n)+dec2(m);
int i=0,c;
int[] arr= {};
while(k>0) {
c = k % 2;
k = k / 2;
arr[i++]=c; //The problem is here. It shows some //error
}
while (i >= 0) {
System.out.print(arr[i--]);
}
}
public static int dec1(int n) {
int a,i=0;
int dec1 = 0;
while(n>0) {
a=n%10;
n=n/10;
dec1= dec1 + (int) (a * Math.pow(2, i));
i++;
}
return dec1;
}
public static int dec2(int m) {
int b,j=0;
int dec2 = 0;
while(m>0) {
b=m%10;
m=m/10;
dec2= dec2 + (int) (b * Math.pow(2, j));
j++;
}
return dec2;
}
}
Here:
int[] arr= {};
creates an empty array. Arrays don't grow dynamically in Java. So any attempt to access any index of arr will result in an ArrayIndexOutOfBounds exception. Because empty arrays have no "index in bounds" at all.
So:
first ask the user for the count of numbers he wants to enter
then go like: int[] arr = new int[targetCountProvidedByUser];
The "more" real answer would be to use List<Integer> numbersFromUsers = new ArrayList<>(); as such Collection classes allow for dynamic adding/removing of elements. But for a Java newbie, you better learn how to deal with arrays first.
Why are you using two different methods to do the same conversion? All you need is one.
You could have done this in the main method.
int k = dec1(n)+dec1(m);
Instead of using Math.pow which returns a double and needs to be cast, another alternative is the following:
int dec = 0;
int mult = 1;
int bin = 10110110; // 128 + 48 + 6 = 182.
while (bin > 0) {
// get the right most bit
int bit = (bin % 10);
// validate
if (bit < 0 || bit > 1) {
throw new IllegalArgumentException("Not a binary number");
}
// Sum up each product, multiplied by a running power of 2.
// this is required since bits are taken from the right.
dec = dec + mult * bit;
bin /= 10;
mult *= 2; // next power of 2
}
System.out.println(dec); // prints 182
An alternative to that is to use a String to represent the binary number and take the bits from the left (high order position).
String bin1 = "10110110";
int dec1 = 0;
// Iterate over the characters, left to right (high to low)
for (char b : bin1.toCharArray()) {
// convert to a integer by subtracting off character '0'.
int bit = b - '0';
// validate
if (bit < 0 || bit > 1) {
throw new IllegalArgumentException("Not a binary number");
}
// going left to right, first multiply by 2 and then add the bit
// Each time thru, the sum will be multiplied by 2 which shifts everything left
// one bit.
dec1 = dec1 * 2 + bit;
}
System.out.println(dec1); // prints 182
One possible way to display the result in binary is to use a StringBuilder and simply insert the converted bits to characters.
public static String toBin(int dec) {
StringBuilder sb = new StringBuilder();
while (dec > 0) {
// by inserting at 0, the bits end up in
// correct order. Adding '0' to the low order
// bit of dec converts to a character.
sb.insert(0, (char) ((dec & 1) + '0'));
// shift right for next bit to convert.
dec >>= 1;
}
return sb.toString();
}
I'm trying to write a method that will calculate if two numbers are relatively prime for an assignment. I'm primarily looking for answers on where to start. I know there is a method gcd() that will do a lot of it for me, but the assignment is pretty much making me do it without gcd or arrays.
I kind of have it started, because I know that I will have to use the % operator in a for loop.
public static boolean relativeNumber(int input4, int input5){
for(int i = 1; i <= input4; i++)
Obviously this method is only going to return true or false because the main function is only going to print a specific line depending on if the two numbers are relatively prime or not.
I'm thinking I will probably have to write two for loops, both for input4, and input5, and possibly some kind of if statement with a logical && operand, but I'm not sure.
Well in case they are relatively prime, the greatest common divider is one, because - if otherwise - both numbers could be devided by that number. So we only need an algorithm to calculate the greatest common divider, for instance Euclid's method:
private static int gcd(int a, int b) {
int t;
while(b != 0){
t = a;
a = b;
b = t%b;
}
return a;
}
And then:
private static boolean relativelyPrime(int a, int b) {
return gcd(a,b) == 1;
}
Euclid's algorithm works in O(log n) which thus is way faster than enumerating over all potential divisors which can be optimized to O(sqrt n).
Swift 4 code for #williem-van-onsem answer;
func gcd(a: Int, b: Int) -> Int {
var b = b
var a = a
var t: Int!
while(b != 0){
t = a;
a = b;
b = t%b;
}
return a
}
func relativelyPrime(a : Int, b: Int) -> Bool{
return gcd(a: a, b: b) == 1
}
Usage;
print(relativelyPrime(a: 2, b: 4)) // false
package stack;
import java.util.Scanner; //To read data from console
/**
*
* #author base
*/
public class Stack {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Scanner in = new Scanner(System.in); // with Scanner we can read data
int a = in.nextInt(); //first variable
int b = in.nextInt(); //second variable
int max; // to store maximum value from a or b
//Let's find maximum value
if (a >= b) {
max = a;
} else {
max = b;
}
int count = 0; // We count divisible number
for (int i=2; i<=max; i++) { // we start from 2, because we can't divide on 0, and every number divisible on 1
if (a % i == 0 && b % i==0) {
count++; //count them
}
}
if (count == 0) { // if there is no divisible numbers
System.out.println("Prime"); // that's our solutions
} else {
System.out.println("Not Prime"); //otherwise
}
}
}
I think that, this is the simple solution. Ask questions in comments.
This is the question I've been assigned:
A so-called “star number”, s, is a number defined by the formula:
s = 6n(n-1) + 1
where n is the index of the star number.
Thus the first six (i.e. for n = 1, 2, 3, 4, 5 and 6) star numbers are: 1, 13, 37,
73, 121, 181
In contrast a so-called “triangle number”, t, is the sum of the numbers from 1 to n: t = 1 + 2 + … + (n-1) + n.
Thus the first six (i.e. for n = 1, 2, 3, 4, 5 and 6) triangle numbers are: 1, 3, 6, 10, 15, 21
Write a Java application that produces a list of all the values of type int that are both star number and triangle numbers.
When solving this problem you MUST write and use at least one function (such as isTriangeNumber() or isStarNumber()
or determineTriangeNumber() or determineStarNumber()). Also you MUST only use the formulas provided here to solve the problem.
tl;dr: Need to output values that are both Star Numbers and Triangle Numbers.
Unfortunately, I can only get the result to output the value '1' in an endless loop, even though I am incrementing by 1 in the while loop.
public class TriangularStars {
public static void main(String[] args) {
int n=1;
int starNumber = starNumber(n);
int triangleNumber = triangleNumber(n);
while ((starNumber<Integer.MAX_VALUE)&&(n<=Integer.MAX_VALUE))
{
if ((starNumber==triangleNumber)&& (starNumber<Integer.MAX_VALUE))
{
System.out.println(starNumber);
}
n++;
}
}
public static int starNumber( int n)
{
int starNumber;
starNumber= (((6*n)*(n-1))+1);
return starNumber;
}
public static int triangleNumber( int n)
{
int triangleNumber;
triangleNumber =+ n;
return triangleNumber;
}
}
Here's a skeleton. Finish the rest yourself:
Questions to ask yourself:
How do I make a Triangle number?
How do I know if something is a Star number?
Why do I only need to proceed until triangle is negative? How can triangle ever be negative?
Good luck!
public class TriangularStars {
private static final double ERROR = 1e-7;
public static void main(String args[]) {
int triangle = 0;
for (int i = 0; triangle >= 0; i++) {
triangle = determineTriangleNumber(i, triangle);
if (isStarNumber(triangle)) {
System.out.println(triangle);
}
}
}
public static boolean isStarNumber(int possibleStar) {
double test = (possibleStar - 1) / 6.;
int reduce = (int) (test + ERROR);
if (Math.abs(test - reduce) > ERROR)
return false;
int sqrt = (int) (Math.sqrt(reduce) + ERROR);
return reduce == sqrt * (sqrt + 1);
}
public static int determineTriangleNumber(int i, int previous) {
return previous + i;
}
}
Output:
1
253
49141
9533161
1849384153
You need to add new calls to starNumber() and triangleNumber() inside the loop. You get the initial values but never re-call them with the updated n values.
As a first cut, I would put those calls immediatly following the n++, so
n++;
starNumber = starNumber(n);
triangleNumber = triangleNumber(n);
}
}
The question here is that "N" neednt be the same for both star and triangle numbers. So you can increase "n" when computing both star and triangle numbers, rather keep on increasing the triangle number as long as its less the current star number. Essentially you need to maintain two variable "n" and "m".
The first problem is that you only call the starNumber() method once, outside the loop. (And the same with triangleNumber().)
A secondary problem is that unless Integer.MAX_VALUE is a star number, your loop will run forever. The reason being that Java numerical operations overflow silently, so if your next star number would be bigger than Integer.MAX_VALUE, the result would just wrap around. You need to use longs to detect if a number is bigger than Integer.MAX_VALUE.
The third problem is that even if you put all the calls into the loop, it would only display star number/triangle number pairs that share the same n value. You need to have two indices in parallel, one for star number and another for triangle numbers and increment one or the other depending on which function returns the smaller number. So something along these lines:
while( starNumber and triangleNumber are both less than or equal to Integer.MAX_VALUE) {
while( starNumber < triangleNumber ) {
generate next starnumber;
}
while( triangleNumber < starNumber ) {
generate next triangle number;
}
if( starNumber == triangleNumber ) {
we've found a matching pair
}
}
And the fourth problem is that your triangleNumber() method is wrong, I wonder how it even compiles.
I think your methodology is flawed. You won't be able to directly make a method of isStarNumber(n) without, inside that method, testing every possible star number. I would take a slightly different approach: pre-computation.
first, find all the triangle numbers:
List<Integer> tris = new ArrayList<Integer>();
for(int i = 2, t = 1; t > 0; i++) { // loop ends after integer overflow
tris.add(t);
t += i; // compute the next triangle value
}
we can do the same for star numbers:
consider the following -
star(n) = 6*n*(n-1) + 1 = 6n^2 - 6n + 1
therefore, by extension
star(n + 1) = 6*(n+1)*n + 1 = 6n^2 + 6n +1
and, star(n + 1) - star(n - 1), with some algebra, is 12n
star(n+1) = star(n) + 12* n
This leads us to the following formula
List<Integer> stars = new ArrayList<Integer>();
for(int i = 1, s = 1; s > 0; i++) {
stars.add(s);
s += (12 * i);
}
The real question is... do we really need to search every number? The answer is no! We only need to search numbers that are actually one or the other. So we could easily use the numbers in the stars (18k of them) and find the ones of those that are also tris!
for(Integer star : stars) {
if(tris.contains(star))
System.out.println("Awesome! " + star + " is both star and tri!");
}
I hope this makes sense to you. For your own sake, don't blindly move these snippets into your code. Instead, learn why it does what it does, ask questions where you're not sure. (Hopefully this isn't due in two hours!)
And good luck with this assignment.
Here's something awesome that will return the first 4 but not the last one. I don't know why the last won't come out. Have fun with this :
class StarAndTri2 {
public static void main(String...args) {
final double q2 = Math.sqrt(2);
out(1);
int a = 1;
for(int i = 1; a > 0; i++) {
a += (12 * i);
if(x((int)(Math.sqrt(a)*q2))==a)out(a);
}
}
static int x(int q) { return (q*(q+1))/2; }
static void out(int i) {System.out.println("found: " + i);}
}