Related
hi I am trying to solve Udemy exercise:
Write a method named hasSharedDigit with two parameters of type int.
Each number should be within the range of 10 (inclusive) - 99 (inclusive). If one of the numbers is not within the range, the method should return false.
The method should return true if there is a digit that appears in both numbers, such as 2 in 12 and 23; otherwise, the method should return false.
I am keep getting true while hasSharedDigit(9,99) I cant discover why..
public class SharedDigit {
public static boolean hasSharedDigit(int number1, int number2){
if((number1 <10 || number1 >99) && (number2 <10 || number2 >99)) {
return false;
}
int numberOneFirstDigit = number1/10;
int numberTwoFirstDigit = number2/10;
int numberOneLastDigit = number1%10;
int numberTwoLastDigit = number2%10;
if(numberOneFirstDigit == numberTwoFirstDigit || numberOneFirstDigit == numberTwoLastDigit || numberOneLastDigit == numberTwoLastDigit) {
return true;
} else {
return false;
}
}
}
If one of the numbers is not within the range, the method should
return false.
Replace
if((number1 <10 || number1 >99) && (number2 <10 || number2 >99))
with
if(number1 <10 || number1 >99 || number2 <10 || number2 >99)
Apart from this, you have missed numberOneLastDigit == numberTwoFirstDigit in the combination of conditions which are supposed to compare the digits i.e. the combination should be
if(
numberOneFirstDigit == numberTwoFirstDigit ||
numberOneFirstDigit == numberTwoLastDigit ||
numberOneLastDigit == numberTwoFirstDigit ||
numberOneLastDigit == numberTwoLastDigit
)
Treating numbers as text
The other Answer and comments solved your direct problem. Just for fun, we can take an entirely different approach.
The idea here is to treat the numbers as text. In doing so, we can address each of your two business rules:
Each number should be within the range of 10 (inclusive) - 99 (inclusive).
Numbers between 10 and 99 happen to have exactly two digits. One digit or 3+ digits means out-of-range.
if there is a digit that appears in both numbers
By collecting into a Set the code point of each character in the string that is our first number, we have a distinct collection for which we can get the intersection of the same for the second number’s string. If the intersection, the resulting modified Set, has a size over 0, then we know digits are shared.
To explain the code below… The codePoints method generates an IntStream, a sequence of int numbers, one for each code point number defined in Unicode for each character in our string that represents our input integer. The boxed call converts those int primitives into Integer objects. Adding those Integer objects to a Set automatically makes them distinct, weeding out automatically any duplicate digits.
See this code run live at IdeOne.com.
private boolean twoIntsAreInRangeAndShareDigits ( int n1 , int n2 )
{
String n1String = Integer.toString( n1 );
String n2String = Integer.toString( n2 );
// Check for negative numbers, meaning out-of-range, not 10-99.
if ( n1String.concat( n2String ).contains( "-" ) ) { return false; }
// Check for exactly 2 digits, meaning within range, 10-99.
if ( ( n1String.length() == 2 ) && ( n2String.length() == 2 ) )
{ // Numbers are within range.
// Check for common digits.
Set < Integer > n1CodePoints = n1String.codePoints().boxed().collect( Collectors.toSet() );
Set < Integer > n2CodePoints = n2String.codePoints().boxed().collect( Collectors.toSet() );
n1CodePoints.retainAll( n2CodePoints );
boolean sharesDigit = ( n1CodePoints.size() > 0 );
return sharesDigit;
}
else // Else 1 or 3+ digits mean numbers are out-of-range.
{ return false; }
}
I am not arguing that this approach is better, just interesting as a different way of thinking about the problem.
You're missing a comparison here. What you have is f1 == f2 || f1 == l2 || l1 == l2 but what's missing it l1 == f2, e.g. 12 and 23 would return false with your code because
1 != 2 (f1 == f2 fails)
1 != 3 (f1 == l2 fails)
2 != 3 (l1 == l2 fails)
your code is missing the 2 == 2 (l1 == f2) so add ... || numberOneLastDigit == numberTwoFirstDigit to the comparison condition.
As the others already stated, your check is also wrong as it requires both numbers to be out of range so if just one is, it doesn't return false.
To make it easier, try to turn the condition around so that both numbers must be in range:
if(!(number1 >= 10 && number1 <=99 && number2 >= 10 && number2 <= 99)) {
return false;
}
Often it might also be easier to read and maintain the code if you'd "name" the conditions:
boolean n1InRange = number1 >= 10 && number1 <=99;
boolean n2InRange = number2 >= 10 && number2 <=99;
if( !(n1InRange && n2InRange) { ... }
//or
if( !n1InRange || !n2InRange ) { ... }
This is my Solution
public static boolean hasSharedDigit(int x, int y){
if( (x < 10 || x > 99) || (y < 10 || y > 99)){
return false;
}
int xFirst = x / 10;
int yFirst = y / 10;
int xLast = x % 10;
int yLast = y % 10;
if((xFirst == yFirst || xLast == yLast) || (xFirst == yLast || xLast == yFirst)){
return true;
} return false;
}
So i have a string in military time format : "1532" corresponding to 3:32pm.
I'm trying to write a method to check if each digit in time string is an appropriate digit. So the first element cannot be greater than 2 or equal to 0, and so forth. Currently, my code doesn't run past the second log statement and I'm hoping you guys could help!
cheers!
String mOpen = "1532";
Log.d("hoursTesting","pass1, length is > 2");
if(mOpen.getText().length() == 4)
{
Log.d("hoursTesting","pass2, length is == 4");
char[] tempString = mOpen.getText().toString().toCharArray();
if(tempString[0] != 0 && tempString[0] < 3)
{
Log.d("hoursTesting","pass3, first index is != 0 and < 3");
if(tempString[0] == 1)
{
Log.d("hoursTesting","pass4, first index is 1");
if(tempString[2] <= 5)
{
Log.d("hoursTesting","pass5, third index is <= 5, success!");
}
}
else //tempString[0] is equal to 2
{
Log.d("hoursTesting","pass4, first index is 2");
if(tempString[1] < 4)
{
Log.d("hoursTesting","pass5, second index is <3");
if(tempString[2] <= 5)
{
Log.d("hoursTesting","pass6, third index is <= 5, success!");
}
}
}
}
}
tempString contains characters, not numbers.
i.e. '0' not 0 etc.
Easiest fix is to compare characters e.g. tempString[0] == '1' Alternatively, you can do something like int digit1 = tempString[0] - '0'; - but that kind of assumes you already know you just have digits in the string.
Note that cos of those clever ASCII guys and their tricky character set '0' < '1' < '2' etc, so you can still say if (str[0] < '2') etc. You just need to be a bit careful that you are only dealing with digits.
Personally I'd convert the first 2 chars to a number and the second 2 chars to a number and then just check 0 <= number1 <= 23 and 0 <= number2 <= 59.
You are comparing char with int here:
if(tempString[0] != 0 && tempString[0] < 3)
It should work like this:
if(tempString[0] != '0' && tempString[0] < '3')
I would substring the hours and minutes components and then check to see if each one be in range:
public boolean isTimeValid(String mOpen) {
int hours = Integer.parseInt(mOpen.substring(0, 2));
int minutes = Integer.parseInt(mOpen.substring(2));
if ((hours >= 0 && hours <= 24) && (minutes >= 0 && minutes <= 59)) {
return true;
}
else {
return false;
}
}
Problem 5: 2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
I have solved the problem 5 of Project Euler
Here is the Java code:
static long FindLcm(long a,long b)
{
long lcm,hcf = 0;
long i=1;
long ger=a>b?a:b;
while(i<ger)
{
if((a%i==0) && (b%i==0))
hcf=i;
i++;
}
lcm=(a*b)/hcf;
return lcm;
}
static void FindMultiple()
{
long lcm=1;
for(long i=2;i<=20;i++)
{
lcm=FindLcm(lcm,i);
}
System.out.println("Lcm="+lcm);
}
How can optimize this?
Your FindMultiple() method is not bad,
static void FindMultiple()
{
long lcm=1;
for(long i=2;i<=20;i++)
{
lcm=FindLcm(lcm,i);
}
System.out.println("Lcm="+lcm);
}
it implements a fairly good algorithm. Your problem is that your FindLcm() contains a nasty performance bug.
static long FindLcm(long a,long b)
{
long lcm,hcf = 0;
long i=1;
// This sets ger to max(a,b) - why?
long ger=a>b?a:b;
// This would return a wrong result if a == b
// that never happens here, though
while(i<ger)
{
if((a%i==0) && (b%i==0))
hcf=i;
i++;
}
lcm=(a*b)/hcf;
return lcm;
}
You are looping until you reach the larger of the two arguments. Since the cumulative LCMs grow rather fast, that takes a lot of time. But the GCD (or HCF, if you prefer) of two (positive) numbers cannot be larger than the smaller of the two. So looping only until the smaller of the two arguments is reached makes the number of iterations at most 20 here, do that 19 times (for i = 2, ..., 20), it's a trivial amount of computation.
Changing to
long ger = a < b ? a : b;
while(i <= ger) {
gives me (adding timing code, not measuring the printing):
17705 nanoseconds
Lcm=232792560
So less than 20 microseconds for the computation. We can easily push that below 6 microseconds if we use the euclidean algorithm to find the greatest common divisor,
static long gcd(long a, long b) {
while(b > 0) {
a %= b;
if (a == 0) return b;
b %= a;
}
return a;
}
and below 5 if we directly use the GCD as
lcm *= i/gcd(lcm,i);
in FindMultiple().
You're solution is more or less brute force which is why it's taking so long. We know that 2520 is the lcm of (1,2,...,9,10) which means two useful things: 1.) We can start checking factors at 11 and 2.) The answer is a multiple of 2520.
You're searching for the Greatest Common Divisor (gcd) of the answer and the next number in your sequence (similar to a bubble sort). You could just check to see if your current answer is divisible by the next factor and if not then add your current answer to itself until the answer is divisible by the next factor. For Example:
static long findLCM(long a, long b) {
long lcm = (a>b) ? a : b;
while (lcm % b != 0) {
lcm += a;
}
return lcm;
}
Since we started with lcm = a, we know that as long as we add a's to lcm then lcm will always be divisible by a. Now, we just need to make some multiple of a divisible by b. This process should cut out many steps of first finding the gcd as well as iterating from 2 through 10.
i did it like this, which was the easiest way i could think of. it's also a little faster than yours.
for(int i = 190; ; i += 190) {
if(i % 3 == 0
&& i % 4 == 0
&& i % 6 == 0
&& i % 7 == 0
&& i % 8 == 0
&& i % 9 == 0
&& i % 11 == 0
&& i % 12 == 0
&& i % 13 == 0
&& i % 14 == 0
&& i % 15 == 0
&& i % 16 == 0
&& i % 17 == 0
&& i % 18 == 0
&& i % 20 == 0) {
System.out.println(i);
break;
}
}
Here are 4 different methods to obtain the result (4 different ways to obtain GCD) + the total time. All of them are based on the following observation:
a*b
lcm(a,b) = ----------
gcd(a,b)
where:
LCM = Least Common Multiple
GCD = Greatest Common Divisor
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
public class A {
final static int N = 20;
static Map<Integer, String> messages = new HashMap<>();
static {
messages.put(0, "Euler - difference");
messages.put(1, "modulo - recursive");
messages.put(2, "modulo - iterative");
messages.put(3, "BigInteger implementation");
}
private static long GCD0(long x, long y) {
while (x != y) {
if (x > y) {
x -= y;
} else {
y -= x;
}
}
return x;
}
private static long GCD1(long x, long y) {
if (x % y == 0) {
return y;
}
return GCD1(y, x % y);
}
private static long GCD2(long x, long y) {
long aux;
while (x % y != 0) {
aux = y;
y = x % y;
x = aux;
}
return y;
}
private static long GCD3(long x, long y) {
BigInteger xx = BigInteger.valueOf(x);
BigInteger yy = BigInteger.valueOf(y);
return xx.gcd(yy).longValue();
}
private static void doIt(int pos) throws Exception {
System.out.print("\n" + messages.get(pos));
printSpaces(25, messages.get(pos).length());
Class cls = Class.forName("A");
Object obj = cls.newInstance();
Method method = cls.getDeclaredMethod("GCD" + pos, long.class,
long.class);
long start = System.nanoTime();
long p = 1;
for (int i = 2; i <= N; i++) {
p = (p * i) / (long) method.invoke(obj, p, i);
}
long stop = System.nanoTime();
System.out.println("\tTime: " + (stop - start) / 1000 + " microseconds");
System.out.println(p);
}
private static void printSpaces(int total, int actualLength) {
for (int i = 0; i < total - actualLength; i++) {
System.out.print(" ");
}
}
public static void main(String[] args) throws Exception {
doIt(0);
doIt(1);
doIt(2);
doIt(3);
}
}
Output:
Euler - difference Time: 137205 microseconds
232792560
modulo - recursive Time: 1240 microseconds
232792560
modulo - iterative Time: 1228 microseconds
232792560
BigInteger implementation Time: 2984 microseconds
232792560
P.S.: I used reflection to call those methods easier, but you can call the method directly to obtain a better performance + a better readability.
int i = 20;
while (true)
{
if (
(i % 1 == 0) &&
(i % 2 == 0) &&
(i % 3 == 0) &&
(i % 5 == 0) &&
(i % 7 == 0) &&
(i % 9 == 0) &&
(i % 11 == 0) &&
(i % 13 == 0) &&
(i % 16 == 0) &&
(i % 17 == 0) &&
(i % 19 == 0) )
{
break;
}
i += 20;
}
S.O.P(i);
C++ Program with minimum iteration... very much resemble to Daniel Fischer
#include<iostream>
using namespace std;
int main()
{
int num = 20;
long lcm = 1L;
for (int i = 2; i <= num; i++)
{
int hcf = 1;
for (int j = 2; j <= i; j++)
{
if (i % j == 0 && lcm % j == 0)
{
hcf = j;
}
}
lcm = (lcm * i) / hcf;
}
cout << lcm << "\n";
}
This method uses brute force, but skips as soon as a number fails instead of continuing to compare the remainders. Heck, it never checks for 20 unless 19 has passed already, which actually makes it pretty efficient.
#include<stdio.h>
int a = 1, b = 1, rem;
int main() {
while (b < 20){
rem = a % b;
if (rem != 0){
a++;
b = 1;
}
b++;
}
printf("%d is the smallest positive number divisible by all of the numbers from 1 to 20.", a);
}
A Non Brute Force Method
This one is instantaneous! Doesn't even take a second. Run the code to understand the logic. It's written in C
#include <stdio.h>
int main() {
int primes[8]={2,3,5,7,11,13,17,19};
int primes_count[8]={0,0,0,0,0,0,0,0};
int i,j,num,prime_point;
int largest_num=1;
printf("\nNUM");
for(j=0;j<8;j++)
printf("\t%d",primes[j]);
for(i=2;i<=20;i++) {
num=i;
int primes_count_temp[8]={0,0,0,0,0,0,0,0};
for(j=0;j<8;j++) {
while(num%primes[j]==0) {
num=num/primes[j];
primes_count_temp[j]++;
}
}
for(j=0;j<8;j++)
if(primes_count_temp[j]>primes_count[j])
primes_count[j]=primes_count_temp[j];
printf("\n %d",i);
for(j=0;j<8;j++)
printf("\t %d",primes_count_temp[j]);
}
printf("\nNET");
for(j=0;j<8;j++)
printf("\t%d",primes_count[j]);
printf("\n");
for(i=0;i<8;i++)
while(primes_count[i]) {
largest_num*=primes[i];
primes_count[i]--;
}
printf("The answer is %d \n",largest_num);
return 0;
}
Now if a number is divisible by X it will be divisible by its prime factors also. So if a number is divisible by 20 it will be divisible by its prime factors. And there are 8 prime factors under 20. I take each number under 20 and find its prime factors, also see the power of the prime factor and keep a count of the highest power.
Once you're done. Multiply all the prime factors raised to their highest power.
my Solution for this in python. this is so simple and use pure Math rules
get the Least Common Multiple
def getLCM (x, y):
return x*y/getGCD(x,y)
get the Greatest Common Divisor
def getGCD(a,b):
while(True):
if(a%b != 0):
temp = b
b = a%b
a = temp
else:
return b
break
Find the Least Common Multiple of, LCM of prev two numbers and next number in list.
LCM(LCM of prev two numbers,next number in list)
num_list = list(range(1,21))
finalLCM = 1
for i in num_list:
finalLCM = getLCM(finalLCM,i)
print(finalLCM)
Full Python Code
def getLCM (x, y):
return x*y/getGCD(x,y)
def getGCD(a,b):
while(True):
if(a%b != 0):
temp = b
b = a%b
a = temp
else:
return b
break
num_list = list(range(1,21))
finalLCM = 1
for i in num_list:
finalLCM = getLCM(finalLCM,i)
print(finalLCM)
we have create an array which was common divisible eg: if any number is divisible by 20 then no need to divisible by 2,4,5,10
<?php
$chk=20;
$div=array(11,12,13,14,15,16,17,18,19,20);
for($number=1;1;$number++){
$chk=$number;
foreach($div as $value){
if($number%$value!=0){
$chk=0;
$number+=$value;
break;
}
}
if($chk!=0){break;}
}
echo $chk;
?>
Given an integer, how could you check if it contains a 0, using Java?
1 = Good
2 = Good
...
9 = Good
10 = BAD!
101 = BAD!
1026 = BAD!
1111 = Good
How can this be done?
Do you mean if the decimal representation contains a 0? The absolute simplest way of doing that is:
if (String.valueOf(x).contains("0"))
Don't forget that a number doesn't "inherently" contain a 0 or not (except for zero itself, of course) - it depends on the base. So "10" in decimal is "A" in hex, and "10" in hex is "16" in decimal... in both cases the result would change.
There may be more efficient ways of testing for the presence of a zero in the decimal representation of an integer, but they're likely to be considerably more involved that the expression above.
If for some reason you don't like the solution that converts to a String you can try:
boolean containsZero(int num) {
if(num == 0)
return true;
if(num < 0)
num = -num;
while(num > 0) {
if(num % 10 == 0)
return true;
num /= 10;
}
return false;
}
This is also assuming num is base 10.
Edit: added conditions to deal with negative numbers and 0 itself.
You can convert it to a string and check if it contains the char "0".
int number = 101;
if( ( "" + number ).contains( "0" ) ) {
System.out.println( "contains the digit 0" );
}
Integer.toString(yourIntValue).contains("0");
Here is a routine that will work detect zeros in integers. To make it work with any representation (decimal, hex, octal, binary), you need to pass in the base as a parameter.
public static boolean hasZero(int num, int base) {
assert base > 0 : "must have positive non-zero base";
if (num == 0)
return true;
while(num != 0) {
if (num % base == 0) {
return true;
}
else {
num = num / base;
}
}
return false;
}
public static void main(String args[]) {
System.out.println(hasZero(10, 10)); // true (base 10 int)
System.out.println(hasZero(-12, 10)); // false (base 10 int)
System.out.println(hasZero(0x10, 16)); // true (hex is base 16)
System.out.println(hasZero(0x1A, 16)); // false (hex is base 16)
}
I don't know if this is easier but here is another way.
Split the number into an array of ints. Then sort and check if the first element is zero.
E.g
int n = 14501;
// after splitting
int na = {1, 4, 5, 0, 1};
// after sorting
int na = {0, 1, 1, 4, 5};
Not using Java, but it's not exactly hard to convert from C++
PS. Shame on anyone using string conversion.
bool Contains0InBase10( unsigned int i, unsigned int& next )
{
unsigned int divisor = 10;
unsigned int remainder = 0;
while( divisor <= i )
{
unsigned int newRemainder = i%divisor;
if( newRemainder - remainder == 0)
{
// give back information allowing a program to skip closer to the next
// number that doesn't contain 0
next = i + (divisor / 10) - remainder;
return true;
}
divisor *= 10;
remainder = newRemainder;
}
return false;
}
Was asked this question recently and did not know the answer. From a high level can someone explain how Java takes a character / String and convert it into an int.
Usually this is done like this:
init result with 0
for each character in string do this
result = result * 10
get the digit from the character ('0' is 48 ASCII (or 0x30), so just subtract that from the character ASCII code to get the digit)
add the digit to the result
return result
Edit: This works for any base if you replace 10 with the correct base and adjust the obtaining of the digit from the corresponding character (should work as is for bases lower than 10, but would need a little adjusting for higher bases - like hexadecimal - since letters are separated from numbers by 7 characters).
Edit 2: Char to digit value conversion: characters '0' to '9' have ASCII values 48 to 57 (0x30 to 0x39 in hexa), so in order to convert a character to its digit value a simple subtraction is needed. Usually it's done like this (where ord is the function that gives the ASCII code of the character):
digit = ord(char) - ord('0')
For higher number bases the letters are used as 'digits' (A-F in hexa), but letters start from 65 (0x41 hexa) which means there's a gap that we have to account for:
digit = ord(char) - ord('0')
if digit > 9 then digit -= 7
Example: 'B' is 66, so ord('B') - ord('0') = 18. Since 18 is larger than 9 we subtract 7 and the end result will be 11 - the value of the 'digit' B.
One more thing to note here - this works only for uppercase letters, so the number must be first converted to uppercase.
The source code of the Java API is freely available. Here's the parseInt() method. It's rather long because it has to handle a lot of exceptional and corner cases.
public static int parseInt(String s, int radix) throws NumberFormatException {
if (s == null) {
throw new NumberFormatException("null");
}
if (radix < Character.MIN_RADIX) {
throw new NumberFormatException("radix " + radix +
" less than Character.MIN_RADIX");
}
if (radix > Character.MAX_RADIX) {
throw new NumberFormatException("radix " + radix +
" greater than Character.MAX_RADIX");
}
int result = 0;
boolean negative = false;
int i = 0, max = s.length();
int limit;
int multmin;
int digit;
if (max > 0) {
if (s.charAt(0) == '-') {
negative = true;
limit = Integer.MIN_VALUE;
i++;
} else {
limit = -Integer.MAX_VALUE;
}
multmin = limit / radix;
if (i < max) {
digit = Character.digit(s.charAt(i++), radix);
if (digit < 0) {
throw NumberFormatException.forInputString(s);
} else {
result = -digit;
}
}
while (i < max) {
// Accumulating negatively avoids surprises near MAX_VALUE
digit = Character.digit(s.charAt(i++), radix);
if (digit < 0) {
throw NumberFormatException.forInputString(s);
}
if (result < multmin) {
throw NumberFormatException.forInputString(s);
}
result *= radix;
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}
result -= digit;
}
} else {
throw NumberFormatException.forInputString(s);
}
if (negative) {
if (i > 1) {
return result;
} else { /* Only got "-" */
throw NumberFormatException.forInputString(s);
}
} else {
return -result;
}
}
I'm not sure what you're looking for, as "high level". I'll give it a try:
take the String, parse all characters one by one
start with a total of 0
if it is between 0 and 9, total = (total x 10) + current
when done, the total is the result
public class StringToInt {
public int ConvertStringToInt(String s) throws NumberFormatException
{
int num =0;
for(int i =0; i<s.length();i++)
{
if(((int)s.charAt(i)>=48)&&((int)s.charAt(i)<=59))
{
num = num*10+ ((int)s.charAt(i)-48);
}
else
{
throw new NumberFormatException();
}
}
return num;
}
public static void main(String[]args)
{
StringToInt obj = new StringToInt();
int i = obj.ConvertStringToInt("1234123");
System.out.println(i);
}
}
Find the length of the String (s) (say maxSize )
Initialize result = 0
begin loop ( int j=maxSize, i =0 ; j > 0; j--, i++)
int digit = Character.digit(s.charAt(i))
result= result + digit * (10 power j-1)
end loop
return result
this is my simple implementation of parse int
public static int parseInteger(String stringNumber) {
int sum=0;
int position=1;
for (int i = stringNumber.length()-1; i >= 0 ; i--) {
int number=stringNumber.charAt(i) - '0';
sum+=number*position;
position=position*10;
}
return sum;
}
Here is what I came up with (Note: No checks are done for alphabets)
int convertStringtoInt(String number){
int total =0;
double multiplier = Math.pow(10, number.length()-1);
for(int i=0;i<number.length();i++){
total = total + (int)multiplier*((int)number.charAt(i) -48);
multiplier/=10;
}
return total;
}
Here is my new approach which is not in a math way.
let n = 12.277;
// converting to string
n = n.toString();
let int = "";
for (let i = 0; i < n.length; i++) {
if (n[i] != ".") {
int += n[i];
} else {
break;
}
}
console.log(Number(int));