Magic Number - The Quest for the Simplest - java

Is there any better logic that can be applied to magic numbers?
Or is there a magic number that I am missing out on?
Please help me out with this simplest working code!
A Magic number is a number whose sum of digits eventually leads to 1.
Example#1: 19 ; 1+9 =10 ; 1+0 = 1. Hence a magic number.
Example#2: 226; 2+2+6=10; 1+0 =1. Hence a magic number.
Example#3: 874; 8+7+4=19; 1+9=10; 1+0=1. Hence a magic number.
boolean isMagic ( int n ) {
return n % 9 == 1;
}

Well, I'm not 100% that the code you placed would work to get a "magic number", but my approach to the problem would be different.
First, I'd receive a String, so that I can get the different digits of the number with a String.charat.
Then I'd use a while cycle to sum the numbers until it gets a single digit number, then check if it's 1.
The code would be
boolean isMagicNumber(String number) {
int[] digits = new int[number.length()];
int sum = 99;
while(sum/10 >= 1) {
sum = 0;
for(int i = 0; i < number.length(); i++) {
sum += Integer.parseInt(""+number.charAt(i));
}
if(sum == 1) {
return true;
}
}
return false;
}
There might be a better solution, but this is what I'd do to solve the problem.

Related

How to sum consecutive equal digits in a number in Java

The following question was asked in my last interview (yesterday), and I'm trying to solve it since then (couldn't solve it in the interview).
Sorry for any grammar mistakes or any logical mistakes, I don't have the question, it was written by memory:
You are given a number in a string format, for example: "14438832066".
You got to sum up the consecutive equal digits in that number. If no
consecutive equal digit was found, just add the digit to the result.
for example: solution(19938832066) => 11831632012
Explanation: first digit is 1.
The second and third digits are both 9 which means they will turn into 18 in the result string.
So on
with the rest of the digits (as you can see, the last 2 digits are both 6 which means they will turn into 12 in the result string).
You are required to do that for the result string as well, if needed, until no equal consecutive digits are found in the number.
Example:: number: 14438832066 solution( "19938832066") ->"11831632012" -> "2831632012"
Explanation: first result is 11831632012, but then you can see that there are still equal consecutive digits : the first and the
second digits are both 1. So process that number as well.
You are given a string and must return a string.
My solution:
I couldn't write the solution, I don't know why. It's a pretty simple question, I thought going recursive at first but didn't want to complex things.
I wrote 2 helper methods:
one that returns a boolean whether the number consists of equal consecutive digits.
one that actually makes the business logic:
turn the string into a char array
create a counter that will count instances of the same digit - (int counter = 1).
loop on the array from the first to the one before the last element :
inside the loop:
//equal digit was found - increment counter and continue to next digit
if char[i] == char[i+1] then counter++
//calculation in case we are done counting the same digit
else if counter > 0 then result.append(counter*digit[i])
// if no consecutive equal digit was found
else result.append(digit[i])
end loop: return result
Problems I had:
I created the counter inside the loop, so each iteration it got rested. took me few minutes to realize.
I had troubles realizing that 'int(digit[i])' doesn't give me the numeric value of the char, it gives the ASCII value. I had to use "Character.getNumericValue" (don't remember the exact name of the method).
Because of these problems, it took me 45 minutes to write the solution which in the end didn't even work.
I'll be glad to get a working solution, and even better - to get any feedback and tips on my solution and what, in your opinion, were my mistakes.
Thank you.
Your pseudo-code seems alright, as far as it goes. What's missing is that you don't repeatedly check the result string to see if another pass is required. I also show how you don't need to remember the API to convert a character to a digit; if you know the digits are decimal, you can interpret them yourself. As an interviewer, I would accept that there is an API that you can't precisely remember or your home-brew solution as equally valid.
String transform(String number) {
while (true) {
String result = collapse(number);
if (result.equals(number)) return result;
number = result;
}
}
private static String collapse(String number) {
StringBuilder result = new StringBuilder();
for (idx = 0; idx < number.length(); ) {
int mark = idx;
int digit = digitAt(number, idx++);
while (idx < number.length() && digitAt(number, idx) == digit) ++idx;
result.append((idx - mark) * digit);
}
return result.toString();
}
private static int digitAt(String num, int index) {
char ch = number.charAt(index);
if (ch < '0' || ch > '9') throw new IllegalArgumentException();
return ch - '0';
}
The preceding is a naïve approach that transforms the string until there are no changes. I suspect there might be a more "elegant" approach that works from left to right through the input in a single pass, but it would take some thought, and I probably couldn't come up with that in an interview.
Here's an algorithm that uses recursion and a for-loop to add consecutive equal digits. I think the code is pretty self-explanatory but please ask if you have any queries.
public static String addConsecutiveDigits(String number) {
char[] arr = number.toCharArray();
StringBuilder result = new StringBuilder();
boolean foundConsecutive = false; // boolean flag for checking if the number contained consecutive equal digits
for (int i = 0; i < arr.length; i++) {
int digit = arr[i] - '0'; //Subtracting ascii values to get integer values
int newNumber = digit;
if (i != arr.length - 1) {
int nextDigit = arr[i + 1] - '0';
if (digit == nextDigit) { // check if the digits are consecutive digits
newNumber = digit + nextDigit;
i++; // increment i as we have already added the i+1 digit
foundConsecutive = true;
}
}
result.append(newNumber);
}
if (!foundConsecutive) // if no consecutive equal digits were found then return the result;
return result.toString();
else // recurse to check for more consecutive equal digits
return addConsecutiveDigits(result.toString());
}
I'm not a Java guy, so this code might not be ideal but I would do something like this:
public String solve(String input)
{
String result = "";
int i = 0;
while (i < input.length())
{
var first = input.charAt(i);
if (i == input.length() - 1){
result += first;
break;
}
var second = input.charAt(i + 1);
if (first == second){
result += (Character.getNumericValue(first) + Character.getNumericValue(second));
i += 2;
} else {
result += first;
i += 1;
}
}
return result;
}
For the second part, I would just run the function in a loop until the result matches the input.

Plus one leetcode

I am doing a question on leetcode, 66. Plus One.
You are given a large integer represented as integer array digits, where each digits[i] is the ith digit of the integer. The digits are ordered from most significant to least significant in left-to-right order. The large integer does not contain any leading 0's.
Increment the large integer by one and return the resulting array of digits.
Example 1
Input: digits = [1,2,3]
Output: [1,2,4]
Explanation: The array represents the integer 123.
Incrementing by one gives 123 + 1 = 124.
Thus, the result should be [1,2,4].
My solution is:
class Solution {
public int[] plusOne(int[] digits) {
int num = 0;
for (int a : digits) {
num = 10*num + a;
}
int n=num+1;
String str=String.valueOf(n);
int arr[]=new int[str.length()];
for(int i=0;i<str.length();i++){
arr[i]=str.charAt(i)-'0';
}
return arr;
}
}
I am getting many test cases failed, one being:
Input:
[9,8,7,6,5,4,3,2,1,0]
Output:
[1,2,8,6,6,0,8,6,1,9]
Expected:
[9,8,7,6,5,4,3,2,1,1]
Can anyone help me with it?
Think before you leap. And consider the edges.
Why would they do the seemingly idiotic move of storing an number, digit by digit, in an int array? Makes no sense, right?
Except... computers aren't magic. int can't represent any number. A computer's storage is not infinite. Specifically, an int covers 32 bits (4 bytes), and thus can only represent at most 2^32 different numbers. int 'uses' its alloted space of 2^32 by dividing it evenly amongst positive and negative numbers, but negative numbers get one more (because the '0' is in the positive space). In other words, all numbers from -2^31 to +2^31-1, inclusive.
9876543210 is larger than that.
You're trying to turn that array of digits into an int and that is a dead end. Once you do that, you get wrong answers and there is no fixing this. your algorithm is wrong. You can figure this stuff out, and you should always do that with leetcode-style problems, by first carefully reading the assignment. The assignment covers the limits. It says how large these arrays can be, and I'm sure it says that they can be quite large; large enough that the number inside it is larger than 2^31-1. Probably larger than 2^63-1 (which a long can reach).
Then you know the algorithm you need to write can't involve 'turn it into an int first'. That's usually the point (many problems are trivial if small, but become interesting once you make things large).
The algorithm they want you to write must not involve any conversion whatsoever. Increment the array in place. This isn't hard (just think about it: without converting anything, how do you turn [1, 2, 3] into [1, 2, 4]? That should be simple. Then think about how to deal with [1, 9, 9]. Finally, think about how to deal with [9, 9, 9]. Then you've covered all the cases and you have your answer.
In continuation to the detailed explanation of rzwitserloot, in case you are interested in code for the problem.
class Solution {
public int[] plusOne(int[] digits) {
int size = digits.length;
int i=0;
for(i = size-1 ; i >= 0 ; i--){
if (digits[i] != 9) {
digits[i] += 1;
break;
} else {
digits[i] = 0;
}
}
if(i == -1) {
int[] newDigits = new int[size+1];
newDigits[0] = 1;
return newDigits;
}
return digits;
}
}
This is a pretty trivial task, but in some test cases the value is too high to represent even as long, so the best candidate is BigInteger.
public int[] plusOne(int[] digits) {
BigInteger val = BigInteger.ZERO;
for (int i = 0; i < digits.length; i++)
val = val.multiply(BigInteger.TEN).add(BigInteger.valueOf(digits[i]));
val = val.add(BigInteger.ONE);
String str = val.toString();
digits = str.length() == digits.length ? digits : new int[str.length()];
for (int i = 0; i < digits.length; i++)
digits[i] = str.charAt(i) - '0';
return digits;
}
P.S. Sure, you can do this without BigInteger.
public int[] plusOne(int[] digits) {
boolean carry = true;
for (int i = digits.length - 1; carry && i >= 0; i--) {
carry = digits[i] == 9;
digits[i] = carry ? 0 : digits[i] + 1;
}
if (carry) {
int[] tmp = new int[digits.length + 1];
tmp[0] = 1;
System.arraycopy(digits, 0, tmp, 1, digits.length);
digits = tmp;
}
return digits;
}
Think about a mileage counter in a car. How does it work?
Whenever a 9 turns around, it turns the number left to it too.
So for incrementing by one, you'd start from the right, increment by one and if you incremented it to a 10, set it to a 0 instead and continue with the next digit to the left. If you reached the leftmost digit and still didnt finish, add a 1 to the left and set everything else to 0.
Example:
8
9 <- incremented rightmost
10 <- 9 turned to a 10, leftmost digit reached, add a 1 to the left and set everything else to 0
...
18
19 <- incremented rightmost
20 <- 9 turned to a 10, set to 0 instead, increment the next one to the left (1 -> 2), finished
...
108
109 <- incremented rightmost
110 <- 9 turned to a 10, set to 0 instead, increment the next one to the left (1 -> 2), finished
...
998
999 <- incremented rightmost
1000 <- 9 turned to a 10, set to 0 instead, increment the next one to the left, turned to a 10 too, set to 0 instead, ...
import java.util.stream.Collectors;
import java.util.stream.IntStream;
class Scratch {
public static void main(String[] args) {
int[] digits = new int[0];
for (int i = 0; i < 100; i++) {
digits = plusOne(digits);
System.out.println(IntStream.of(digits).mapToObj(Integer::toString).collect(Collectors.joining()));
}
}
public static int[] plusOne(int[] digits) {
boolean finished = false;
for (int i = digits.length - 1; !finished && i >= 0; i--) {
if (++digits[i] % 10 == 0) {
digits[i] = 0;
} else {
finished = true;
}
}
if (!finished) {
// not finished after exiting the loop: every digit was turned from a 9 to a 10 -> we need one digit more
// initialize a new array with a length of 1 more digit, set the leftmost (index 0) to 1 (everything else is 0 by default)
digits = new int[digits.length + 1];
digits[0] = 1;
}
return digits;
}
}
plus one in leetcode solve on dart language
class Solution {
List<int> plusOne(List<int> digits) {
for(int i=digits.length - 1; i>=0; i--){
if(digits[i] < 9){
++digits[i];
return digits;
}
digits[i]=0;
}
List<int> ans = List.filled(digits.length+1, 0);
ans[0]=1;
return ans;
}
}
Here is my solution:
Runtime: 0 ms, faster than 100.00% of Java online submissions for Plus One.
Memory Usage: 40.8 MB, less than 92.31% of Java online submissions for Plus One. for Plus One.
public int[] plusOne(int[] digits) {
for(int i=digits.length-1;i>=0;i--) {
if(digits[i]<9) {
digits[i]=digits[i]+1;
return digits;
}else {
digits[i]=0;
if(i==0) {
digits= new int[digits.length+1];
digits[0]=1;
}
}
}
return digits;
}
My solution:
Runtime: 0 ms, Memory Usage: 2.1 MB,
play.golang link: https://go.dev/play/p/Vm28BdaIi2x
// function to add one digit based on diff scenarios
func plusOne(digits []int) []int {
i := len(digits) - 1
// while the index is valid and the value at [i] ==
// 9 set it as 0 and move index to previous value
for i >= 0 && digits[i] == 9 {
digits[i] = 0
i--
}
if i < 0 {
//leveraging golang's simplicity with append internal method for array
return append([]int{1}, digits...)
} else {
digits[i]++
}
return digits
}

Java- working with an integer

Write a static method called digitsInARow that takes an integer n as a parameter and that returns the highest number of digits that appear in a row in the base-10 representation of n. For many numbers the answer will be 1 because they don't have adjacent digits that match. But for a number like 3555585, the answer is 4 because there are four occurrences of the digit 5 that appear in a row. You are NOT allowed to use a String to solve this problem. You may assume that the value passed to the method is greater than or equal to 0.
public static int digitsInARow(int n) {
if (n / 10 == 0) {
return 1;
}
int count = 0;
int count1 = 0;
while (n > 0) {
int digit = n % 10;
int a = n / 10;
if (digit == a % 10) {
count++;
} else {
count1 = Math.max(count1, count);
count = 0;
}
n = n / 10;
}
return Math.max(count, count1);
}
I know the if statement is messed up. I am trying to figure out a way to compare consecutive digits WITHOUT using Integer class or String class. Any suggestions?
The problem with your code is that count keeps track of the current count, not of the highest count. You need to add a variable that tracks the highest count as well, and update it each time you process a digit, before resetting count back to zero.
Don't forget to update the highest count when you exit the loop, in case then-current count is greater than the previously found max.

Prime Number Calculations Help Java

I am a novice, please excuse my lack of organization.
Okay, so what I did was I made an array filled with all the prime numbers between 8 and 100. What I want to do now is make another array that finds all the prime numbers between 101-200. So allow me to explain how I did the first part:
//Prime1 is an dynamic integer array which stores all the prime numbers between 8 and 100
int arrayCounter = 0;
for(int primeTest = 8; primeTest<=100; primeTest++)
{
if(primeTest%2!=0 && primeTest%3!=0 && primeTest%5!=0 && primeTest%7!=0)
{
Prime1.add(primeTest); //adds the prime numbers to array
arrayCounter = arrayCounter +1;
}
else
{
arrayCounter = arrayCounter + 1;
}
}
Now back to the main issue, rather than writing "if(primeTest % "prime#" !=0)" I would like to be able to use modulus through the entire Prime1 array and see if all the values do not equal zero... Let me elaborate.
for(int primeTest2 = 101; primeTest2 <= 200; primeTest2++)
{
for(int arrayCounter2 = 0; arrayCounter2 < Prime1.size(); arrayCounter2++)
{
if(primeTest2 % Prime1.get(arrayCounter2) != 0 )
{
Prime2.add(primeTest2);
}
}
}
//please forgive any missing braces
^^So what happens here is that I take a value starting at 101 and modulus it with the first value of the Prime1 array. As you know, this may give me a false positive because 11 (the first prime number in the array) may still show true even with numbers which are not prime. This is why I need to be able to test a number with all the values in the array to ensure that it cannot be divided by any other prime number (meaning that it is prime).
Your method is extremely inefficient, nevertheless, here is how you can fix it:
for (int primeTest2 = 101; primeTest2 <= 200; primeTest2++)
{
boolean prime = true;
for (int arrayCounter2 = 0; arrayCounter2 < Prime1.size(); arrayCounter2++)
{
if (primeTest2 % Prime1.get(arrayCounter2) == 0)
{
prime = false;
break;
}
}
if (prime)
Prime2.add(primeTest2);
}
BTW, for the first set of prime numbers, it is sufficient to use 2, 3, 5, 7, 11, 13.
Take a boolean and set it to true. If the number can be divided by any of your primes from 8 to 100 without a remainder, than set it to false. If it is still true after testing every number, add the tested number to the Prime2 array, otherwise continue with the next number. Example:
for(int n = 101; n <= 200; n++)
{
boolean isPrime = true;
for(Integer p : Prime1)
if(n % p == 0 )
{
isPrime = false;
break;
}
if(isPrime)
Prime2.add(n);
}
But there are better alorithms out there to check if a number is prime or to calculate alle primes below n. For example the Sieve of Eratosthenes.

Nested "FOR-loops" not working

I am doing an excercise in the book "Java how to program". The excercise wants me to write a method that determines if a number is "prime". (A "Prime number" is a positiv integer which is only dividable with itself and 1). Then I am supposed to implement the method in an application that displays all integers up to 10 000.
I use "double-values" to test whether the remainder is 0 or not, to test dividability.
Anyway, I just don´t get the program to work, it displays all numbers fro 3, with an increement on how many times each number is displayed (3 44 555 etc). Can anyone please tell me what I´m doing wrong?
The code is the following:
public class Oppgave625
{
public static void main(String[] args)
{
for(double a = 2; a <= 10000; a++)
{
for(double b = 1; b < a; b++)
{
if (prime(a, b) !=0)
{
System.out.printf("%.0f ", prime(a, b));
}
}
}
}
static double prime(double x, double y)
{
if (x % y != 0)
{
return x;
}
else
{
return 0;
}
}
}
Use int instead. double is not good for this purpose
you might want to read this article to understand the use of the % Operator for floating point numbers.
Actually, there were many individual errors in here. I shortened the prime() function to the point where it was only a modulo op, so I was able to inline it. Second, I inverted the test so it checked for numbers that do not have a remainder, and continues to the next number as soon as it finds a divisor. Third, I changed b = 1 so that we do not check for numbers divisible by 1, because this would result to all numbers. Finally, I only print out the numbers for which we do not discover a divisor. The final result:
public static void main(String[] args) {
outer:
for (int a = 2; a <= 1000; a++) {
for (int b = 2; b < a; b++) {
if (a % b == 0) {
continue outer;
}
}
System.out.println(a);
}
}
Edit: I forgot to mention, I also changed the types from floats to ints, since I'm sure that's what you meant.
It's great that you posted sample code for this, but there are several things that are wrong:
you should not use a floating point type for this, but an int or a long. Floating point types should never be used for precise values.
you are making two calls to your prime function, effectively doubling the required steps
your prime function only tells you whether two numbers divide themselves evenly, it does not tell you whether one is a prime or not
for prime numbers, you should use a more efficient algorithm instead of calculating the same values over and over for each number. Look up Sieve of Eratosthenes.
You are approaching the problem like this: The number A is NOT prime, whenever i can find a number B that can divide A without a remainder.
Bur right now, you print out A whenever it is not dividable by B.
Instead you could say: whenever A not divisible by B, increase B. When i found a B to divide A, quit the inner loop, print nothing.
When i found no B, print A and quit loop.
Furthermore, you only have to test for divisibility of A until (a/2)-1.
A prime number is a number that is only divisible by one and itself. That is: one number. Your code is comparing two numbers as in the Euclidean algorithm for testing coprime-ness. This is very different than testing if a number is prime.
Your code should look something like this:
for i = 2 to 10,000 {
if( isPrime(i) ){
print i
}
}
function isPrime( int n ){
for i = 2 to n {
next if i == n
if( n % i == 0 ){
return 0;
}
}
return 1;
}
boolean isPrime = true;
for (int i = 2; i<=100; i++){
for(int j = 2; j<=i/2; j++){
isPrime = true;
if (i%j==0){
isPrime = false;
break;
}
}
if (isPrime){
Log.d("PrimeNumber",""+i);
}
}

Categories