How do I identify 2 separate 2-digit numbers in a String? - java

I am trying to find a way to identify 1 or 2 digit numbers in a string (there can't be any 3 digit numbers), add them together so they must be between 80 and 95.
For some reason, the code is not working, as it is always returning false, even when it should (in theory) return true.
ex. "Hi 57 how are you 30" returns false
Thank you in advance for your help!
("line" is the name of the String.)
public boolean isDig(){
int total=0;
int h;
int length = line.length();
for(h=0; h < length-1; h++) {
if (Character.isDigit(line.charAt(h))){
if (Character.isDigit(line.charAt(h+1))){
if (Character.isDigit(line.charAt(h+2))){
return false;
}
else {
total= total+(line.charAt(h)+line.charAt(h+1));
h++;
}
}
else {
total= total+(line.charAt(h));
}
}
if (total>=80 && total<=95){
return true;
}
else {
return false;
}
}

The main problem in the code is that line.charAt(h) isn't the numeric value of the digit at position h. It's the codepoint value, for example '0' is 48.
The easiest way to obtain the numeric value is Character.getNumericValue(line.charAt(h)), and similarly in other places.
You're also missing the multiplication by 10 of the first digit in the pair.
Assuming you know that the string is valid, it's easy enough just to add up any numbers in the string. The fact that they are 2 or 3 digits doesn't really matter from the perspective of obtaining the sum.
int total = 0;
for (int i = 0; i < line.length(); ) {
// Skip past non-digits.
while (i < line.length() && !Character.isDigit(line.charAt(i))) {
++i;
}
// Accumulate consecutive digits into a number.
int num = 0;
while (i < line.length() && Character.isDigit(line.charAt(i))) {
num = 10 * num + Character.getNumericValue(line.charAt(i));
}
// Add that number to the total.
total += num;
}

You should use a regex for this kind of parsing :
public class Example {
public static void main(String[] args) {
String input = "Hi 57 how are you 30";
System.out.println(process(input));
}
private static boolean process(String input) {
Pattern pattern = Pattern.compile(".*?(\\d+).*?(\\d+)");
Matcher matcher = pattern.matcher(input);
if (matcher.matches()) {
int one = Integer.parseInt(matcher.group(1));
int other = Integer.parseInt(matcher.group(2));
System.out.println(one);
System.out.println(other);
int total = one + other;
return total >= 80 && total <= 95;
}
return false;
}
}
Output :
57
30
true

One of the possible solution it to use Regual Expression.
public static boolean isValid(String str) {
// regular expression matches 1 or 2 digit number
Matcher matcher = Pattern.compile("(?<!\\d)\\d{1,2}(?!\\d)").matcher(str);
int sum = 0;
// iterate over all found digits and sum it
while (matcher.find()) {
sum += Integer.parseInt(matcher.group());
}
return sum >= 80 && sum <= 95;
}

Let a java.util.Scanner do the work:
public boolean scan(String line) {
Scanner scanner = new Scanner(line);
scanner.useDelimiter("\\D+");
int a = scanner.nextInt();
int b = scanner.nextInt();
int sum = a + b;
return sum >= 80 && sum <= 95;
}
The invocation of .useDelimiter("\\D+") delimits the string on a regular expression matching non-digit characters, so nextInt finds the next integer. You'll have to tweak it a bit if you want to pick up negative integers.

You could convert the String into an Array and test to see if each element in the String (separated by a space) is a Digit by testing the Integer.parseInt() method on each String element. Here is an example below:
public static boolean isDig(String theString) {
String[] theStringArray = theString.split(" ");
ArrayList<Integer> nums = new ArrayList<Integer>();
for(int x = 0; x < theStringArray.length; x++) {
String thisString = theStringArray[x];
try {
int num = Integer.parseInt(thisString);
nums.add(num);
}catch(NumberFormatException e) {
continue;
}
}
int total = 0;
for(int num: nums) {
total += num;
}
if(total >= 80 && total <= 95) {
return true;
}
else {
System.out.println(total);
return false;
}
}
We first split the original String into an Array based on the empty spaces. We then create an ArrayList that will add each digit in the String to it. We then create a for loop to look at each individual String in the Array and we set up a try-catch block. If we can covert the digit into an int using the Integer.parseInt() method, we will add it to the ArrayList. If not, we will catch the exception and continue the loop with a "continue" statement. Once we break out of the loop, we can create a variable called "total" and create another for loop in order to add each digit in the ArrayList to the total amount. If the total is greater than/equal to 80 and less than/equal to 95, we will return True, or else we will return false. Let's test the code:
String digitTest = "There is a digit here: 50 and a digit here 45";
System.out.println(isDig(digitTest));
The numbers 50 and 45 should equal 95 and our result is:
true

Related

Printing number using recursion in java without its biggest digit

Using recursion I need to input a number and the console will print this number without its highest digit. If it's smaller than 10 it will return 0.
I already found the biggest digit but how can i remove it and print the number without it after?
This is the code for the biggest digit:
public static int remLastDigit(int n){
if(n==0)
return 0;
return Math.max(n%10, remLastDigit(n/10));
}
If i input 12345 i expect the output to be 1234. if i input 9 or less i expect the output to be 0.
Here is my solution:
// call this method
public static int removeLastDigit(int number) {
return removeLastDigitImpl(number, largestDigit(number));
}
private static int removeLastDigitImpl(int number, int largestDigit) {
if (number < 10) { // if the number is a single digit, decide what to do with it
if (number == largestDigit) {
return 0; // if it is the largest digit, remove it
} else {
return number; // if it is not, keep it
}
}
// handle the last digit of the number otherwise
if (number % 10 == largestDigit) {
// removing the digit
return removeLastDigitImpl(number / 10, largestDigit);
} else {
// not removing the digit
return removeLastDigitImpl(number / 10, largestDigit) * 10 + number % 10;
}
}
// this is the same as your attempt
private static int largestDigit(int n){
if(n==0)
return 0;
return Math.max(n%10, largestDigit(n/10));
}
Since you've already found the max digit nicely, here's how you can print the number without it.
public static void main(String[] args) {
printWithoutDigit(2349345, remLastDigit(2349345));
}
public static void printWithoutDigit(int number, int maxDigit) {
Integer.toString(number).chars().filter(digit -> Integer.valueOf(String.valueOf((char)digit))!=maxDigit).forEach(d -> System.out.print((char)d));
}
You could convert your number to a String, or more precisely to a char-array. Then, you can find out where in this array the biggest digit is, remove it and convert your char-array back to an integer.
This would roughly look like this:
int num = 12345; //the number from which you want to remove the biggest digit
char[] numC = String.valueOf(num).toCharArray();
int biggestDigit = 0;
int biggestDigitIndex = 0;
for (int i = 0; i < numC.length; i++) {
if (biggestDigit < Character.getNumericValue(numC[i])) {
biggestDigit = Character.getNumericValue(numC[i]);
biggestDigitIndex = i;
}
//Remove digit at index biggestDigitIndex from numC
//Convert numC back to int
}
Of course, you have to incorporate this into your recursion, which means returning the number you got after converting numC back to int and then feed this into your input parameter again. Also, of course you need to add a check if your number is < 9 in the beginning.

Find consecutive number of 1's

I am trying to find the number of consecutive 1's in a binary.
Example: Convert Decimal number to Binary and find consecutive 1's
static int count = 0;
static int max = 0;
static int index = 1;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
scan.close();
String b = Integer.toBinaryString(n);
char[] arr = b.toCharArray();
System.out.println(arr);
for (int i = 0; i < b.length(); i++) {
if (arr[i] == index) {
count++;
} else {
count = 0;
}
if (count > max) {
max = count;
}
}
System.out.println(max);
}
I am always getting 0. It seems as if the condition is not working in my code. Could you please provide your suggestion on where am I going wrong with this?
Your qusetion is not so clear but AFAIU from your algorithm, you're trying to find number of most repeated 1's. The issue is that when you're doing comparision if (arr[i] == index), the comparison is done with a char and integer because type of arr is char array. Isn't it? To overcome it either you can convert the char array into integer or convert the integer index value into char. I do this to overcome it.
if (arr[i] == index + '0')
It is not an really elegant solution. I assume that you're a student and want you to show what's wrong. If I want to do something like this, I use,
private static int maxConsecutiveOnes(int x) {
// Initialize result
int count = 0;
// Count the number of iterations to
// reach x = 0.
while (x!=0) {
// This operation reduces length
// of every sequence of 1s by one.
x = (x & (x << 1));
count++;
}
return count;
}
Its trick is,
11101111 (x)
& 11011110 (x << 1)
----------
11001110 (x & (x << 1))
^ ^
| |
trailing 1 removed
As I understand correctly, you want to count maximum length of the group of 1 in the binary representation of the int value. E.g. for 7917=0b1111011101101 result will be 4 (we have following groups of 1: 1, 2, 3, 4).
You could use bit operations (and avoid to string convertation). You have one counter (to count amount of 1 in the current group) and max with maximum of all such amounts. All you need is just to check lowest bit for 1 and then rotate value to the right until it becomes 0, like getMaxConsecutiveSetBit1.
Or just do it in a very simple way - convert it to the binary string and count amount of 1 characters in it, like getMaxConsecutiveSetBit2. Also have one counter + max. Do not forget, that char in Java is an int on the JVM level. So you do not have compilation problem with compare char with int value 1, but this is wrong. To check if character is 1, you have to use character - '1'.
public static void main(String[] args) {
try (Scanner scan = new Scanner(System.in)) {
int val = scan.nextInt();
System.out.println(Integer.toBinaryString(val));
System.out.println(getMaxConsecutiveSetBit1(val));
System.out.println(getMaxConsecutiveSetBit2(val));
}
}
public static int getMaxConsecutiveSetBit1(int val) {
int max = 0;
int cur = 0;
while (val != 0) {
if ((val & 0x1) != 0)
cur++;
else {
max = Math.max(max, cur);
cur = 0;
}
val >>>= 1;
}
return Math.max(max, cur);
}
public static int getMaxConsecutiveSetBit2(int val) {
int max = 0;
int cur = 0;
for (char ch : Integer.toBinaryString(val).toCharArray()) {
if (ch == '1')
cur++;
else {
max = Math.max(max, cur);
cur = 0;
}
}
return Math.max(max, cur);
}
Change type of index variable from int to char:
static char index = 1;
to let the comparison made in this line:
if (arr[i] == index)
do its job. Comparing int 1 (in your code this is the value stored in index variable) with char '1' (in your example it's currently checked element of arr[]) checks if ASCII code of given char is equal to int value of 1. This comparison is never true as char '1' has an ASCII code 49 and this is the value that is being compared to value of 1 (49 is never equal to 1).
You might want to have a look at ASCII codes table in the web to see that all characters there have assigned corresponding numeric values. You need to be aware that these values are taken into consideration when comparing char to int with == operaror.
When you change mentioned type of index to char, comparison works fine and your code seems to be fixed.
Using your for loop structure and changing a few things around while also adding some other stats to report which could be useful. I count the total number of 1's in the number, the number of consecutive 1's (groups of 1's), and the greatest number of consecutive 1's. Also your for loop was looping based on the string length and not the array's length which is just sort of nit picky. Here is the code
int count = 0;
int max = 0;
char index = '1';
int consecutiveOnePairs = 0;
int numberOfOnes = 0;
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
String b = Integer.toBinaryString(n);
char[] arr = b.toCharArray();
System.out.println(arr);
for (int i = 0; i < arr.length; i++) {
if (arr[i] == index)
{
count++;
numberOfOnes++;
}
if((i + 1 == arr.length && count > 1) || arr[i] != index)
{
if(count > 1)
consecutiveOnePairs++;
if (count > max)
max = count;
count = 0;
}
}
System.out.println("Total Number of 1's in " + n + " is " + numberOfOnes);
System.out.println("Total Number of Consecutive 1's in " + n + " is " + consecutiveOnePairs);
System.out.println("Greatest Number of Consecutive 1's in " + n + " is " + max);
scan.close();
Output
13247
11001110111111
Total Number of 1's in 13247 is 11
Total Number of Consecutive 1's in 13247 is 3
Greatest Number of Consecutive 1's in 13247 is 6
511
111111111
Total Number of 1's in 511 is 9
Total Number of Consecutive 1's in 511 is 1
Greatest Number of Consecutive 1's in 511 is 9
887
1101110111
Total Number of 1's in 887 is 8
Total Number of Consecutive 1's in 887 is 3
Greatest Number of Consecutive 1's in 887 is 3
If you use Java 8, you can try this snippet:
public int maxOneConsecutive(int x)
{
String intAsBinaryStr = Integer.toBinaryString(x);
String[] split = intAsBinaryStr.split("0");
return Arrays.stream(split)
.filter(str -> !str.isEmpty())
.map(String::length)
.max(Comparator.comparingInt(a -> a)).orElse(0);
}

Count odd digits of a number with recursive method

I tried to write a simple java program which counts how many odd digits there are inside a number (for example, for input "123" the program should return 2). The program instead returns all the digits of the given number. Any idea?
import java.util.*;
//Counts the number of odd digits in an int using recursion
public class OddCount{
public static void main(String[]args){
Scanner in = new Scanner(System.in);
System.out.println("Digit a positive int number: ");
int n = in.nextInt();
System.out.println("The number of odd digits is " + oddDigitCounter(n));
}
public static int oddDigitCounter(int number) {
int result = 0;
if(number<=10){
if(number%2==0)
result = 0;
else
result++;
}
else{
if(number%10!=0){
if((number%10)/2!=0)
result = 1 + oddDigitCounter(number/10);
else
result = 0 + oddDigitCounter(number/10);
}
else{
result = 0 + oddDigitCounter(number/10);
}
}
return result;
}
}
Here is a way to write your recursive method without all the unnecessary conditions.
public static int oddDigitCounter(int number) {
if (number==0) {
return 0;
}
return (number&1) + oddDigitCounter(number/10);
}
Using &1 instead of %2 allows it to work for negative numbers as well as positive ones.1
1 (number&1) is zero for an even number, and one for an odd number, and works regardless of whether the number is positive or negative. For instance, if number==-3 then (number%2)==-1, but (number&1)==1, which is what we want in this case.
Check your code, you are using / instead of % in this if condition:
if((number%10)/2!=0)
It should be:
if((number%10)%2!=0)
In oddDigitCounter() why don't you simply check digit by digit if it's an even or odd one and echo (store) the result?
Recursive approach: at first call you may pass to the function the entire number and then if the number is 1 digit long let the function do the check and return, otherwhise do the check against the 1st digit and pass the others again to the function itself.
Procedural approach: do a simple loop through the digits and do the checks.
You can use following sample:
import java.util.Scanner;
public class NumberOfOddDigist {
private static int count = 0;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("Digit a positive int number: ");
int n = in.nextInt();
countOdd(n);
System.out.println("The number of odd digits is " + count);
in.close();
}
public static void countOdd(int number) {
int remainder = number % 10;
int quotient = (number - remainder) / 10;
if (!(remainder % 2 == 0)) {
count++;
}
number = quotient;
if (number < 10) {
if (!(number % 2 == 0)) {
count++;
}
} else {
countOdd(number);
}
}
}

Find next largest number to given input with specific pattern

I am trying to solve a problem . Hoping for some help here.
Objective: Find a number which is immediate next to input and contains only 4 and 7 in it.
Input : 1234
Output: 4444
Input : 4476
output: 4477
Input : 8327
Output : 44444
I am not looking for incrementing number and each time checking string characters for the pattern. That would be too slow for large numbers.
static String toOutput (int a) {
// I am trying here all the possible other ways
}
Check this answer. Hope this helps :)
private static String toOutput(int n) {
String input = String.valueOf(n+1);
// create input character array and output character array of one more in size
char[] inputChars = input.toCharArray();
char[] outputChars = new char[inputChars.length + 1];
boolean extra = false; //carry forward
// traverse input array from last position to first position
for (int i = inputChars.length - 1; i >= 0; i--) {
// for all other positions except last position check whether number is changed
// (i.e. apart from 4 or 7),
// change all higher digits in output array to 4
if ((i + 1) < inputChars.length) {
if (inputChars[i] != '4' && inputChars[i] != '7') {
for (int j = i + 1; j < inputChars.length; j++) {
outputChars[j + 1] = '4';
}
}
}
// if extra is true that means it is carry forward
if (extra == true) {
inputChars[i] = (char) ((int) inputChars[i] + 1);
}
// if input digit is less than equal to 4 output digit is 4 , extra is false
if (inputChars[i] <= '4') {
outputChars[i + 1] = '4';
extra = false;
}
// if input digit is between 4 to 7 output digit is 7 , extra is false
else if (inputChars[i] <= '7') {
outputChars[i + 1] = '7';
extra = false;
}
// if input digit is more than 7 output digit is 4 , extra is true
else {
outputChars[i + 1] = '4';
extra = true;
}
}
// if carry forward is true, make extra digit to 4 otherwise it is not required
if (extra == true) {
outputChars[0] = '4';
} else {
outputChars[0] = ' ';
}
return new String(outputChars).trim();
}
static String toOutput (long a) {
LinkedList<Long> q = new LinkedList<Long>();
q.add(4L);
q.add(7L);
while(!q.isEmpty()){
Long curr = q.pop();
if(curr>a)
return String.valueOf(curr);
q.add(curr*10+4);
q.add(curr*10+7);
}
return "";
}
This will solve the problem in close to O(LogN)
Since this is fundamentally a manipulation of character strings, a plausible solution is to use string functions, particularly regular expressions. Here's a compact solution:
class Incrementer {
Pattern p;
public Incrementer() {
p = Pattern.compile("(?:([47]*)([0-6]))?(.*)");
}
public String next(String s) {
Matcher m = p.matcher(s);
m.lookingAt();
return (m.group(1)==null
? '4'
: m.group(1) + (m.group(2).charAt(0) >= '4' ? '7' : '4'))
+ m.group(3).replaceAll(".", "4");
}
}
See it here.
(I'm not at all a Java programmer. Coding suggestions welcome.)
The regular expression matches the prefix of any sequence of legal digits (4 or 7) followed by an incrementable digit ( < 7). If that prefix is not matchable, the answer must be one digit longer, so it must start with the smallest legal digit (4). If the prefix is matchable, the prefix must be modified by bumping the last digit to the next legal digit. In both cases, all the digits following the (possibly empty) prefix are replaced with the smallest legal digit.
Of course, this could be done without actual regular expressions. The following essentially uses a state machine which implements the regular expression, so it might be faster. (Personally I find the regex version easier to verify, but YMMV):
public static String next(String s)
{
int toinc = -1;
for (int i = 0; i < s.length(); ++i) {
char c = s.charAt(i);
if (c < '7') {
toinc = i;
if (c != '4') break;
} else if (c > '7') break;
}
char[] outChars;
// Copy the prefix up to and including the character to be incremented
if (toinc < 0) {
outChars = new char[s.length() + 1];
} else {
outChars = new char[s.length()];
for (int i = 0; i < toinc; ++i)
outChars[i] = s.charAt(i);
// Increment the character to be incremented
outChars[toinc] = s.charAt(toinc) >= '4' ? '7' : '4';
}
// Fill with 4's.
for (int i = toinc + 1; i < outChars.length; ++i)
outChars[i] = '4';
return new String(outChars);
}
See it here.
*
public class PatternTest {
private static final char FOUR = '4';
private static final char SEVEN = '7';
public static void main(String[] args) {
Scanner scanner = new Scanner(new InputStreamReader(System.in));
String value = scanner.next();
char startChar = value.charAt(0);
Result result;
if (startChar == FOUR || startChar == SEVEN) {
result = getStartWith4Or7(value);
} else {
result = getNotStartWith4Or7(value);
}
System.out.println("Final value is : " + result.getValue());
}
private static Result getNotStartWith4Or7(String value) {
Result result = new Result();
char startChar = value.charAt(0);
if (startChar < FOUR) {
result.value = value.replaceAll(".", String.valueOf(FOUR));
} else if (startChar > SEVEN) {
result.value = value.replaceAll(".", String.valueOf(FOUR));
result.flag = FOUR;
} else if (startChar > FOUR && startChar < SEVEN) {
result.value = getSubString(value).replaceAll(".", String.valueOf(FOUR));
result.value = String.valueOf(SEVEN) + result.value;
}
return result;
}
private static Result getStartWith4Or7(String value) {
Result result = new Result();
if (value != null && !value.equalsIgnoreCase("")) {
char startChar = value.charAt(0);
if (startChar == FOUR || startChar == SEVEN) {
value = getSubString(value);
result = getStartWith4Or7(value);
result.value = getStartCharUpdate(startChar, result) + result.value;
} else {
result = getNotStartWith4Or7(value);
}
}
return result;
}
private static String getStartCharUpdate(char startChar, Result result) {
String newValue = String.valueOf(startChar);
if (result.flag == FOUR) {
if (startChar == FOUR) {
newValue = String.valueOf(SEVEN);
result.flag = 0;
} else {
newValue = String.valueOf(FOUR);
}
}
return newValue;
}
private static String getSubString(String value) {
int len = value.length();
String finalValue = "";
if (len > 1) {
finalValue = value.substring(1, len);
}
return finalValue;
}
static class Result {
String value = "";
char flag;
public String getValue() {
if (flag == FOUR) {
value = FOUR + value;
}
return value;
}
}
}
*
You can try something like this.
String num = "4476";
double immediateVal = 0;
int length = num.length();
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
for (int i = 0; i < length; i++) {
sb1.append("4");
sb2.append("7");
}
double valNum = Double.parseDouble(num);
double val1 = Double.parseDouble(sb1.toString());
double val2 = Double.parseDouble(sb2.toString());
if (valNum < val1) {
immediateVal = val1;
} else if (val1 <= valNum && valNum < val2) {
if(num.indexOf("4")==0){
int firstIndexOf7=-1;
for(int a=0;a<length;a++){
firstIndexOf7=num.indexOf("7");
if(firstIndexOf7!=-1){
break;
}
}
if(firstIndexOf7!=-1){
StringBuilder sb3=new StringBuilder();
for(int b=0;b<firstIndexOf7;b++){
sb3.append("4");
}
for(int b=firstIndexOf7;b<length;b++){
sb3.append("7");
}
immediateVal=Double.parseDouble(sb3.toString());
}
} else{
immediateVal = val2;
}
}else if(valNum>=val2){
immediateVal=Double.parseDouble(sb1.append("4").toString());
}
System.out.println(immediateVal);
this can help you
static String toOutput(String input){
char[] values = input.toCharArray();
StringBuilder result = new StringBuilder();
int length = values.length;
int currentPosition = 0;
for(char current: values){
Integer currentInt = new Integer(current);
if(currentInt<4){
//fill the string with 4, best result
for(currentPosition;currentPosition<length;currentPosition++){
result.append(4);
}
break;
}
else if(currentInt==4){
result.append(4);
currentPosition++;
continue;
}
else if(currentInt<=7){
result.append(7);
currentPosition++;
continue;
}
else if(currentInt>7){
if(currentPosition=0){
//fill the string with 4 but with length +1, best result
for(currentPosition;currentPosition<=length;currentPosition++){
result.append(4);
}
break;
}
else{
// you need work this case, change last 4 to 7 and fill the rest with 4. enjoy it.
}
}
return result.toString();
}
One approach would be reading the digits right to left and check if that is less than 4 or 7 and add 4 or 7 respectively.
One optimization would be check if first(from left) digit is >7 then its sure that you will have all 4's +1 extra 4`.
You need to take extra care at the left most digit. If the left most digit is greater than 7 you need to add two 4s.
EX: 1234
right to left `4` is `4`
`3` is `4`
`2` is `4`
`1` is `4`
This approach wont work if all the digits in the number are 4 or 7. You need to have one condition and change one or two chars accordingly.
private static String toOutput(int a) {
String s = Integer.toString(a);
StringBuilder sb = new StringBuilder();
if (Integer.valueOf(s.charAt(0)) > 7) {
for(int i=0; i<= s.length(); i++) {
sb.append("4");
}
return sb.toString();
}
for(int i=s.length()-1; i>=0; i--) {
Integer x = Integer.valueOf(i);
if(x <=4) {
sb.append(4);
} else {
sb.append(7);
}
}
return sb.reverse().toString();
}
This is not checking if the number has all 4's or 7's.
I don't think you need to worry about performance for converting a number into a String. You're evaluating a number as if it's a string, so it only makes sense to cast it to string to do the evaluation.
Something like this works and is reasonably fast.
public static int closestNumber(int num) {
for (int i = num + 1; i < Integer.MAX_VALUE; i++) {
if ((i+"").matches("^[47]+$")) {
return i;
}
}
throw new RuntimeException("Your number was too close to Integer's max value!");
}
Ok, I wrote it using mod and no strings:
public static int closestNumber(int num) {
for (int i = num + 1; i < Integer.MAX_VALUE; i++) {
if (containsOnly(i,4,7)) {
return i;
}
}
throw new RuntimeException("Your number was too close to Integer's max value!");
}
public static boolean containsOnly(int evaluate, int numeralA, int numeralB) {
while (evaluate > 0) {
int digit = evaluate % 10;
if (digit != numeralA && digit != numeralB) return false;
evaluate = evaluate / 10;
}
return true;
}
It looks like looking for the first digit that is not 4 or 7 counting from left to right.
Set up a index pointer to record the last index that hold digit "4" and check every digit from left to right.
Initial current pointer index (c) to -1 and set last "4" index (l) to -1
For every digit from left to right
update c (c+=1)
check digit value
digit = 7 -> do nothing
digit = 4 -> l = c
digit < 4 -> this digit change to "4", all remaining digits sets to "4", end check
4 < digit < 7 -> this digit change to "7", all remaining digits sets to "4", end check
digit > 7 -> do necessary change and end check
l = -1 => 444....444 (no. of digit = n+1)
l > -1 => digit at l change to "7", all digits after l change to "4"
Idea
For a n-digit value, if it contains only "4" or "7", you do nothing.
Then, if there is any non "4" or "7", what should it be?
Analyzing the pattern, we need to know the first occurrence of non "4"/"7" digit (from left to right) only and all digits after the digit will change to "4" to minimize the value since 444...444 is the least k-digit value for combination of "4" and "7" for all k.
Consider case Xcccccccc , c is any value
If X in {4,7}, consider case 2.
If X in {1,2,3}, the next value should be 444444444.
If X in {5,6}, the next value should be 744444444.
If X in {8,9}, the next value should be 4444444444
Consider case aaaaXcccc, if a are "4" or "7"
If X in {4,7}, consider case aaaaaXccc.
If X in {0,1,2,3}, the next value should be aaaa44444.
If X in {5,6}, the next value should be aaaa74444.
If X in {8,9}, the next value should be bbbb44444 or bbbbb44444.(b are "4" or "7")
then how to deduce bbbb or bbbbb?
if aaaa does not have any "4", you get bbbbb = 44444 (since aaaa=7777)
if aaaa have "4", you get bbbb ("4" will be replaced by "7", e.g. 474779 => 477444)
Consider case aaaaaaaaX, this should be same as case 2 except no remaining digit need to be handle
Combine case 1-3, when the first occurrence of non "4"/"7" digit is in {8,9}, the difference in change of value depends on whether there is any "4" before the digit.

Iterate through each digit in a number

I am trying to create a program that will tell if a number given to it is a "Happy Number" or not. Finding a happy number requires each digit in the number to be squared, and the result of each digit's square to be added together.
In Python, you could use something like this:
SQUARE[d] for d in str(n)
But I can't find how to iterate through each digit in a number in Java. As you can tell, I am new to it, and can't find an answer in the Java docs.
You can use a modulo 10 operation to get the rightmost number and then divide the number by 10 to get the next number.
long addSquaresOfDigits(int number) {
long result = 0;
int tmp = 0;
while(number > 0) {
tmp = number % 10;
result += tmp * tmp;
number /= 10;
}
return result;
}
You could also put it in a string and turn that into a char array and iterate through it doing something like Math.pow(charArray[i] - '0', 2.0);
Assuming the number is an integer to begin with:
int num = 56;
String strNum = "" + num;
int strLength = strNum.length();
int sum = 0;
for (int i = 0; i < strLength; ++i) {
int digit = Integer.parseInt(strNum.charAt(i));
sum += (digit * digit);
}
I wondered which method would be quickest to split up a positive number into its digits in Java, String vs modulo
public static ArrayList<Integer> splitViaString(long number) {
ArrayList<Integer> result = new ArrayList<>();
String s = Long.toString(number);
for (int i = 0; i < s.length(); i++) {
result.add(s.charAt(i) - '0');
}
return result; // MSD at start of list
}
vs
public static ArrayList<Integer> splitViaModulo(long number) {
ArrayList<Integer> result = new ArrayList<>();
while (number > 0) {
int digit = (int) (number % 10);
result.add(digit);
number /= 10;
}
return result; // LSD at start of list
}
Testing each method by passing Long.MAX_VALUE 10,000,000 times, the string version took 2.090 seconds and the modulo version 2.334 seconds. (Oracle Java 8 on 64bit Ubuntu running in Eclipse Neon)
So not a lot in it really, but I was a bit surprised that String was faster
In the above example we can use:
int digit = Character.getNumericValue(strNum.charAt(i));
instead of
int digit = Integer.parseInt(strNum.charAt(i));
You can turn the integer into a string and iterate through each char in the string. As you do that turn that char into an integer
This code returns the first number (after 1) that fits your description.
public static void main(String[] args) {
int i=2;
// starting the search at 2, since 1 is also a happy number
while(true) {
int sum=0;
for(char ch:(i+"").toCharArray()) { // casting to string and looping through the characters.
int j=Character.getNumericValue(ch);
// getting the numeric value of the current char.
sum+=Math.pow(j, j);
// adding the current digit raised to the power of itself to the sum.
}
if(sum==i) {
// if the sum is equal to the initial number
// we have found a number that fits and exit.
System.out.println("found: "+i);
break;
}
// otherwise we keep on searching
i++;
}
}

Categories