Finding Kaprekars Constant of a number using Java - java

So I had tried this online challenge but got runtime error.Please help.I am new to programming. I have attached the problem statement and my solution.
The Challenge
Using the Java language, have the function KaprekarsConstant(num) take an integer of four digits (with at least two being distinct) and perform the following routine on said number:
Arrange the digits in descending order and in ascending order.
Subtract the smaller number from the bigger number, padding the difference with zeroes if necessary to maintain a four-digit number.
Then repeat step 1 and 2 using the four-digit difference.
Stop when the difference of the two, permuted numbers equals 6174.
Return the number of times that you had to perform steps 1 and 2 before arriving at a difference with the value of 6174.
nb: performing the routine on 6174 will always give you 6174 (7641 - 1467 = 6174).
For example: if num is 3524 your program should return 3: (pass 1) 5432 - 2345 = 3087, (pass 2) 8730 - 0378 = 8352, (pass 3) 8532 - 2358 = 6174.
Here is my solution:
import java.util.*;
import java.io.*;
class Main {
public static int KaprekarsConstant(int num) {
int diff = 0, count = 0;
while (diff != 6174) {
String s1 = String.valueOf(num);
int[] ch1 = new int[s1.length()];
for (int i = 0; i < ch1.length; i++) {
ch1[i] = s1.charAt(i);
}
Arrays.sort(ch1);
String s2 = String.valueOf(ch1);
String s3 = "";
for (int j = s2.length() - 1; j >= 0; j++) {
s3 += s2.charAt(j);
}
int a = Integer.parseInt(s2);
int b = Integer.parseInt(s3);
if (a > b) {
diff = a - b;
} else if (b > a) {
diff = b - a;
} else {
System.out.println("goal cant be reached");
break;
}
count++;
num = diff;
}
return num;
}
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.print(KaprekarsConstant(s.nextLine()));
}
}

Try this code:
/**
* KaprekarConstant
*/
import java.util.InputMismatchException;
import java.util.Scanner;
import java.util.Arrays;
import java.util.Collections;
public class KaprekarConstant {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int inputNumber;
char[] digits;
System.out.print("Enter four digit number: ");
try {
inputNumber = scan.nextInt();
if (checkLength(inputNumber))
throw new Exception();
Kaprekar(inputNumber);
} catch (InputMismatchException e) {
System.out.println("Not a number");
} catch (Exception ex) {
System.out.println("Number must have four digits");
} finally {
scan.close();
}
}
public static void Kaprekar(int target) {
int maximum = 0, minimum = 0, result = 0;
Integer[] digits = new Integer[4];
if (target == 6174)
return;
int i = 0;
while (i < 4) {
digits[i] = target % 10;
target /= 10;
i++;
}
Arrays.sort(digits);
minimum = toInt(digits);
Arrays.sort(digits, Collections.reverseOrder());
maximum = toInt(digits);
result = maximum - minimum;
System.out.println(String.format("%d - %d = %d", maximum, minimum, result));
Kaprekar(result);
}
public static boolean checkLength(int number) {
if (String.valueOf(number).length() < 5 && String.valueOf(number).length() > 3)
return false;
return true;
}
public static int toInt(Integer[] digits) {
int number = 0;
for (int digit : digits) {
number *= 10;
number += digit;
}
return number;
}
}
I think this is best method to find the karpekar constant.

There were some basic syntax & logical errors in your code. I have made appropriate changes in it. See if you understand it.
import java.util.*;
import java.io.*;
public class Main {
public static int KaprekarsConstant(int num) {
int diff = 0, count = 0;
while (diff != 6174) {
String s1 = String.valueOf(num);
char[] ch1 = new char[s1.length()];
for (int i = 0; i < ch1.length; i++) {
ch1[i] = s1.charAt(i);
}
Arrays.sort(ch1);
String s2 = new String(ch1);
String s3 = "";
for (int j = s2.length() - 1; j >= 0; j--) {
s3 += s2.charAt(j);
}
int a = Integer.parseInt(s2);
int b = Integer.parseInt(s3);
if (a > b) {
diff = a - b;
} else if (b > a) {
diff = b - a;
} else {
System.out.println("goal cant be reached");
break;
}
count++;
num = diff;
}
return count;
}
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.print(KaprekarsConstant(s.nextInt()));
}
}

This solution has less lines of code:
import static java.lang.System.out;
import java.util.Arrays;
/**
* #see https://en.wikipedia.org/wiki/6174_%28number%29
*/
public class KaprekarConstant {
public static void main(String[] args) {
assert(count(3524) == 3);
assert(count(3087) == 2);
assert(count(8352) == 1);
assert(count(6174) == 1);
out.println("All passed.");
}
public static int count(int start) {
int ct = 0;
do {
start = calc(start);
ct++;
} while (start != 6174);
return ct;
}
static int calc(int n) {
String n1s = String.format("%04d", n);
char[] chs = n1s.toCharArray();
Arrays.sort(chs);
n1s = new String(chs);
String n2s = new StringBuilder(new String(n1s)).reverse().toString();
int n1 = Integer.parseInt(n1s);
int n2 = Integer.parseInt(n2s);
return Math.max(n1, n2) - Math.min(n1, n2);
}
}
Here is a Python implementation:
def kc_count(start_int):
def kc_calc(n):
ns1 = ''.join(sorted("%04d" % n))
ns2 = ns1[::-1]
return max(int(ns1), int(ns2)) - min(int(ns1), int(ns2))
ct = 0;
while True:
start_int = kc_calc(start_int)
ct += 1
if start_int == 6174:
break
return ct
assert(kc_count(3524) == 3)
assert(kc_count(3087) == 2)
assert(kc_count(8352) == 1)
assert(kc_count(6174) == 1)

Related

Is there a way to iterate through an array without using loops?

I'm trying to write a code that will output all possible passwords from a given array recursively,
e.g. given the input
"ab"
will output the next:
a
b
aa
ab
ba
bb
the problem is that I'm instructed to use only one loop in the crack() function below and that's it. I cannot use any other functions, just those two.
This is what I've got so far:
import java.util.*;
public class PasswordGen {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Please enter a string:");
char array[] = sc.next().toCharArray();
System.out.println("All Combination:");
crack(array);
sc.close();
}
static void crack(char[] array) {
for (int i = 1; i <= array.length; i++) {
generate(array, i, "", array.length);
}
}
static void generate(char[] array, int i, String string, int length) {
//recursion stopping if condition is meet
if (i == 0) {
System.out.println(string);
return;
}
for (int j = 0; j < length; j++) {
String charArray = string + array[j];
generate(array, i -1, charArray , length);
}
return;
}
}
Is there a way to get the same output without using the for loop in the generate() function?
(see code below).
static void generate(char[] array, int i, String string, int length) {
//recursion stopping if condition is meet
if (i == 0) {
System.out.println(string);
return;
}
for (int j = 0; j < length; j++) {
String charArray = string + array[j];
generate(array, i -1, charArray , length);
}
Any suggestions/better way to do it?
Not sure if this answers your question, but here is a class that does what you want without any for loop:
import java.util.*;
import java.util.stream.*;
class Bruteforcer {
private List<Integer> state = Collections.singletonList(0);
private final String allowedChars;
private final Integer maxLength;
public Bruteforcer(String allowedChars, Integer maxLength){
assert allowedChars != null;
assert allowedChars.length() > 0;
assert maxLength > 0;
this.allowedChars = allowedChars;
this.maxLength = maxLength;
}
public String next(){
final var allIndexesAreLastChar = this.state.stream().allMatch(i -> i == this.allowedChars.length() - 1);
final var currentLength = this.state.size();
if (currentLength > this.maxLength){
return null;
}
final var nextPassword = this.state.stream()
.map(i -> this.allowedChars.substring(i, i + 1))
.collect(Collectors.joining(""));
if (allIndexesAreLastChar){
this.state = Collections.nCopies(currentLength + 1, 0);
return nextPassword;
}
this.state = IntStream.range(0, currentLength)
.mapToObj(i -> {
final var current = this.state.get(currentLength - 1 - i);
final var mustIncrement = i == 0 || this.state.get(currentLength - i) == this.allowedChars.length() - 1;
if (mustIncrement){
return current == this.allowedChars.length() - 1 ? 0 : current + 1;
}
return current;
})
.collect(Collectors.toList());
Collections.reverse(this.state);
return nextPassword;
}
}
class FindPasswordApplication {
public static void main(String[] args) {
final var bruteforcer = new Bruteforcer("ab", 2);
for (var i = 0; i < 10; i ++){
final var password = bruteforcer.next();
System.out.println(password);
}
}
}

Why my code is incorrect (processing string)?

I'm currently doing an online course on hyperskill. There's a task:
The password is hard to crack if it contains at least A uppercase
letters, at least B lowercase letters, at least C digits and includes
exactly N symbols. Also, a password cannot contain two or more same
characters coming one after another. For a given numbers A, B, C, N
you should output password that matches these requirements.
And here's my code:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int upper = scan.nextInt();
int lower = scan.nextInt();
int digits = scan.nextInt();
int quantity = scan.nextInt();
String symbolsUpper = "QWERTYUIOPASDFGHJKLZXCVBNM";
String symbolsLower = "qwertyuiopasdfghjklzxcvbnm";
String symbolsDigits = "1234567890";
boolean exit = false;
Random random = new Random();
ArrayList<Character> password = new ArrayList<>();
if (upper > 0) {
for (int i = 0; i < upper; i++) {
password.add(symbolsUpper.charAt(random.nextInt(symbolsUpper.length())));
}
}
if (lower > 0) {
for (int k = 0; k < lower; k++) {
password.add(symbolsLower.charAt(random.nextInt(symbolsLower.length())));
}
}
if (digits > 0) {
for (int z = 0; z < digits; z++) {
password.add(symbolsDigits.charAt(random.nextInt(symbolsDigits.length())));
}
}
if (quantity - digits - upper - lower > 0) {
for (int m = 0; m < (quantity - digits - upper - lower); m++) {
password.add(symbolsDigits.charAt(random.nextInt(symbolsDigits.length())));
}
}
Collections.shuffle(password);
while (!exit) {
if (password.size() > 1) {
for (int i = 1; i < password.size(); i++) {
if (password.get(i).equals(password.get(i - 1))) {
char buffer = password.get(i);
password.remove(i);
password.add(buffer);
i--;
} else {
exit = true;
}
}
} else {
exit = true;
}
}
StringBuilder buildPassword = new StringBuilder();
for (Character character : password) {
buildPassword.append(character);
}
System.out.println(buildPassword);
}
}
When I run the code in IntelliJ IDEA, the program works just fine, however, the hyperskill platform doesn't accept this code as the right one.
The topic is "Processing string".
Can anyone here tell me please, what am I doing wrong? Is there a better way to write this code?
Can anyone here tell me please, what am I doing wrong?
The problem is that, due to the nature of random numbers, you might be very unlucky in the characters which are picked. This can result in two problems:
You can pick the same characters from the pool of characters. When you create a password using the input 0 0 0 2 it might be possible that two same digits are picked. As an example the password "55" can never satisfy the condition of having not two characters next to each other be the same, no matter how many time you shuffle it.
When the password is very long and you find two characters same next to each other you put one of the character to the end. This can happen twice for the same character. This means that the password "........44........44........." can result in the password ".........4.........4...........44", and now you have two same characters again (at the end).
Is there a better way to write this code?
Yes.
I don't know if you are trying for best performance, but here is a fun solution:
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int uppers = scan.nextInt();
int lowers = scan.nextInt();
int digits = scan.nextInt();
int quantity = scan.nextInt();
int freeChoices = quantity - uppers - lowers - digits;
if (freeChoices < 0) {
System.exit(1);
}
ThreadLocalRandom r = ThreadLocalRandom.current();
StringBuilder password = new StringBuilder();
boolean isPasswordReady = false;
int lastUpper = -1, lastLower = -1, lastDigit = -1;
PasswordPart[] options = PasswordPart.values();
while (!isPasswordReady) {
int partChoice = r.nextInt(0, options.length);
switch (options[partChoice]) {
case DIGIT:
if (digits > 0 || freeChoices > 0) {
CharIndexHolder result = options[partChoice].get(lastDigit, -1, r);
password.append(result.c);
lastDigit = result.i;
if (digits == 0) {
freeChoices--;
} else {
digits--;
}
}
break;
case LOWER:
if (lowers > 0 || freeChoices > 0) {
CharIndexHolder result = options[partChoice].get(lastLower, lastUpper, r);
password.append(result.c);
lastLower = result.i;
if (lowers == 0) {
freeChoices--;
} else {
lowers--;
}
}
break;
case UPPER:
if (uppers > 0 || freeChoices > 0) {
CharIndexHolder result = options[partChoice].get(lastUpper, lastLower, r);
password.append(result.c);
lastUpper = result.i;
if (uppers == 0) {
freeChoices--;
} else {
uppers--;
}
}
break;
}
isPasswordReady = uppers == 0 && lowers == 0 && digits == 0 && freeChoices == 0;
}
System.out.println(password.toString());
}
enum PasswordPart {
UPPER("QWERTYUIOPASDFGHJKLZXCVBNM"), LOWER("qwertyuiopasdfghjklzxcvbnm"), DIGIT("1234567890");
private String pool;
PasswordPart(String pool) {
this.pool = pool;
}
public CharIndexHolder get(int lastIndex, int additionalIndex, ThreadLocalRandom random) {
int i = random.nextInt(0, pool.length());
while (i == lastIndex || i == additionalIndex) {
i = random.nextInt(0, pool.length());
}
return new CharIndexHolder(pool.charAt(i), i);
}
}
private static class CharIndexHolder {
char c;
int i;
CharIndexHolder(char c, int i) {
this.c = c;
this.i = i;
}
}

Numbers to letters in java (like old mobile phones' keyboard)

Just like older mobile phones' keypads work. I should input a string of numbers and the program should print out a text based on those numbers.
e.g: Input: 4448 9666777557777 should output to: ITWORKS.
Here's my code so far but it's not printing out anything. Could you please tell me what's wrong with it and what could've I done better?
Scanner sc = new Scanner(System.in);
String[] letters = {
"0",
"1",
"ABC",
"DEF",
"GHI",
"JKL",
"MNO",
"PQRS",
"TUV",
"WXYZ"
};
System.out.println("Write something.");
String numbers = sc.nextLine();
char[] toChar = numbers.toCharArray();
int count = 0;
for (int index = 0; index < toChar.length; index++) {
if (toChar[index] >= '2' && toChar[index] <= '9') {
if (index > 0 && toChar[index] == toChar[index - 1]) {
count++;
}
else if (count > 0) {
System.out.print(letters[toChar[index - 1] - '0'].charAt(count - 1));
count = 0;
}
}
}
How about this?
import java.util.Scanner;
public class Test {
private static final String[] letters = {
"0", "1", "ABC", "DEF", "GHI", "JKL", "MNO", "PQRS", "TUV", "WXYZ"
};
private static char getChar(int digit, int count) {
while (count > letters[digit].length()) {
count -= letters[digit].length();
}
return letters[digit].charAt(count - 1);
}
private static String getString(String input) {
int lastDigit = 0, count = 1;
String result = "";
for (int i = 0; i < input.length(); i++) {
int currentDigit = input.charAt(i) - '0';
if (currentDigit >= 2 && currentDigit <= 9) {
if (lastDigit == 0) {
lastDigit = currentDigit;
} else if (currentDigit == lastDigit) {
count++;
} else {
result += getChar(lastDigit, count);
lastDigit = currentDigit;
count = 1;
}
}
}
return result + getChar(lastDigit, count);
}
public static void main(String[] args) {
try (Scanner scanner = new Scanner(System.in)) {
System.out.println("Write something");
System.out.println(getString(scanner.nextLine()));
}
}
}
I enhanced the problem decomposition. It works for all examples OP has shown so far.
If I understand your intention correctly, count should increment only if current digit is the same as previous:
for (int pos = 1, char c = toChar[0], int count = 1; pos <= toChar.length; pos++, count = 1) {
int n = letters[c - '0'].length;
while (pos < toChar.length && c == toChar[pos] && count < n) {
pos++;
count++;
}
System.out.println(letters[c - '0'].charAt(count - 1));
if (pos < toChar.length - 1) {
c = toChar[++pos];
}
}
This code will help you!
Check this one
public class Denene {
public static String getChar(String cha)
{
String [] chars= {"0","1","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
String[] strSplit = cha.split(" "); //7777 88 7777 2 66 8
int len=strSplit.length;
char r;
char []ar =new char[len];
for(int i=0;i<len;i++){
String str=strSplit[i];
ar[i]= chars[Integer.parseInt(String.valueOf(str.charAt(0)))].charAt(str.length()-1);
}
return new String(ar);
}
public static void main(String[] args) {
System.out.println("Enter any number .....");
System.out.println(getChar(new Scanner(System.in).nextLine())); //Output : susant
}
}

Can some help me figure out why my zeroes are not appending?

So I've been working on this BigNum multiplication method (in short the method takes in a BigNum other and is supposed to return the product of two large positive integers without using the bigint class) for a while and I'm almost done however, I am still having issues appending zeroes. My helper method does not seem to be adding correctly either (as an ex. 444*4 should return as "1776" however it returns as "161616".) I need someone to debug this and help me figure out why it isn't working. Any help is appreciated.
Here's the result I get when I try doing 444*444 as an example
the expected output should be:
1776
17760
177600
197136
actual output with my code:
161616
1616160
1616160
3393936
My methods
/**Multiplies two <tt>BigNum<tt> values together and returns a new
*<tt>BigNum<tt> object with the resulting value.
*
*#param other object
*#returns a new BigNum with resulting value
*/
public BigNum mult(BigNum other) {
BigNum tmp = new BigNum();
BigNum acc = new BigNum();
String s="";
int count=0;
for(int i= 0; i < other.num.length() ; i++) { //each digit x of other
tmp = this.mult(Character.getNumericValue(other.num.charAt(i)));
if(i > 0) {
for(int j=0; j < i; j++) {
s = tmp.num + "0";
}
}else {
s = tmp.num;
}
tmp=new BigNum(s);
count++;
acc = acc.add(tmp);
}
return acc;
}
/**Helper method that adds the other value a set of number of times, 0-9
*
*#param and int n and other object
*#returns resulting value
*/
public BigNum mult(int n) {
String result;
int carry;
if(n==0){
result="0";
}
else{
carry =0;
result = "";
}
for(int i=this.num.length()-1; i >=0; i--){
int temp = n * Character.getNumericValue(this.num.charAt(i))
result=(temp%10) + result;
carry = temp/10;
if(carry > 0){
result = carry + result;
}
}
return new BigNum(result);
}
Using String to implement BIGNUM multiply is rather slow, however it works.
Change your code as follows:
public BigNum mult(BigNum other) {
BigNum tmp = new BigNum();
BigNum acc = new BigNum();
String s="";
int count=0;
for(int i= 0; i < other.num.length() ; i++) { //each digit x of other
tmp = this.mult(Character.getNumericValue(other.num.charAt(i)));
if(i > 0) {
s = tmp.num;
for(int j=i; j > 0 ; j--) {
s = s + "0";
}
}else {
s = tmp.num;
}
tmp=new BigNum(s);
count++;
acc = acc.add(tmp);
}
return acc;
}
public BigNum mult(int n) {
String result;
int carry;
if(n==0){
result="0";
}
else{
carry =0;
result = "";
}
for(int i=this.num.length()-1; i >=0; i--){
int temp = n * Character.getNumericValue(this.num.charAt(i));
// add carry first
carry = temp/10;
if(carry > 0){
int lastnum=(result.length()==0)?0:
Character.getNumericValue(result.charAt(result.length()-1));
lastnum=lastnum+carry;
result = (result.length()==0)?"":result.substring(0, result.length()-1); // remove the last num
result = result + lastnum;
}
result= result + (temp%10);
}
return new BigNum(result);
}
Next time you should also paste your add() method. Here's my implementation of add(), if anyone's interested (pretty ugly I have to say):
private BigNum add(BigNum other) {
StringBuilder sb = new StringBuilder();
int sum, carry=0;
String large, small;
if(this.num.length()>=other.num.length()) {
large=this.num; small=other.num;
} else {
large=other.num; small = this.num;
}
int len = Math.min(this.num.length(), other.num.length());
for(int i=len-1; i>=0; i--) {
sum = Character.getNumericValue(large.charAt(large.length()-len+i)) +
Character.getNumericValue(small.charAt(i)) +
carry;
carry=(sum>=10)?1:0;
sb.insert(0, String.valueOf(sum).charAt((sum>=10)?1:0));
}
if(large.length()==small.length()) {
if(carry==1) sb.insert(0, 1);
} else {
sum = Character.getNumericValue(large.charAt(large.length()-(len+1)))+carry;
sb.insert(0, String.valueOf(sum).charAt(0));
}
for(int i=large.length()-(len+2); i>=0; i--) {
sb.insert(0, large.charAt(i));
}
num = sb.toString();
return this;
}
All of these methods goes into this BigNum class:
public class BigNum {
String num;
public BigNum() {
num=new String();
}
public BigNum(String s) {
this.num=s;
}
... methods here...
}
Use the following logic: 5 * 2 = 5 + 5 + 5 + 5 + 5
public class BigNum {
int value;
public BigNum(int value) {
this.value = value;
}
public BigNum mult(BigNum other) {
int result = 0;
for (int i = 0; i < value; i++) {
result += other.getValue();
};
return new BigNum(result);
}
public int getValue() {
return value;
}
#Override
public String toString() {
return "BigNum [value=" + value + "]";
}
public static void main(String[] args) {
System.out.println(new BigNum(444).mult(new BigNum(444)));
}
}

Currently compiling, but receiving nothing but end to program?

import java.util.Scanner;
public class PD {
public static void main(String[] args) {
Scanner input = new Scanner (System.in);
System.out.print("Enter your number: " );
int number = input.nextInt();
for (int count = 2; count < number; count++) {
String blank = "";
String Snumber = count + blank;
if (isPalindromic(count) && isPrime(count) &&
isPalindromic((int)(Snumber.length())) &&
isPrime((int)(Snumber.length()))){
System.out.println( count + "is double palidromic prime");
}
else
continue;
}
}
// method to find palindromic
public static boolean isPalindromic(int count) {
String blank = "";
String convert = count + blank;
for (int i = 0, q = 1; i <= (convert.length()/2 - 1); i++, q++) {
if (convert.substring(i,q) == convert.substring(convert.length() - q, convert.length() - i)){
return true;
}
}
return false;
}
// method to find prime
public static boolean isPrime(int count ) {
for (int divisor = 2; divisor <= count/2; divisor++) {
if (count % divisor == 0) {
return false;
}
}
return true;
}
}
Currently the thing compiles and ask for input, but it always results in nothing.
Does someone see something wrong with my program that is obvious wrong.
Overall, the program receives input and has to look through values 2 until it hits the value the user wants and print the ones that follow the if statement.
Your isPalindromic method is not functioning properly. It is not returning true for palindromic numbers. Change it to this:
public static boolean isPalindromic(int count) {
String blank = "";
String convert = count + blank;
int n = convert.length();
for (int i = 0; i < (n / 2 + 1); i++) {
if (convert.charAt(i) != convert.charAt(n - i - 1)) {
return false;
}
}
return true;
}

Categories