Transform double for Loop to Stream? - java

I'm just curious if i can switch this
for (String arg : args) {
int number = Integer.parseInt(arg);
int checksum = 0;
for (int digits = 0; digits < 10; digits++) {
checksum += number % 10;
number /= 10;
}
System.out.println(checksum);
}
}
into a piped Java Stream (only that condition, no recursive method etc.).
My first attempt was
public static void main(String... args) {
Stream.of(args)
.?
}
with then somehow use a function like:
class FunctionTest implements Function<String, Integer> {
#Override
public Integer apply(String s) {
int number = Integer.parseInt(s);
int checksum = 0;
IntStream.range(1,10).reduce(number, ()-> ?)
checksum += number % 10;
number /= 10;
return checksum;
}
}
But I guess I come to a dead end with that...
Does someone has a better idea or is it actually impossible?

Arrays.stream(args)
.map(Integer::parseInt)
.map(number -> {
int sum = 0;
for(int i = 0; i < 10; i ++) {
sum += number % 10;
number /= 10;
}
return sum;
})
.forEach(System.out::println);
Or alternatively (note this would not work for negative numbers):
Arrays.stream(args)
.map(number -> number.split(""))
.map(Arrays::stream)
.map(strStream -> strStream.mapToInt(Integer::parseInt))
.map(IntStream::sum)
.forEach(System.out::println);
This one splits the string into its individual character strings, maps them to integers and then sums them
And finally, also a positive number only solution:
Arrays.stream(args)
.map(CharSequence::chars)
.map(chars -> chars.map(Character::getNumericValue))
.map(IntStream::sum)
.forEach(System.out::println);

An approach assuming input are Strings
This is somewhat obscure due to the fact there is only IntStream, but no CharStream. CharSequence.chars() gives an IntStream. '0' maps to 48 according to ASCII, '1' to 49 etc. So you can just subtract 48 to get the int value.
String[]x={"1495","34","333333","-13"};
Arrays.stream(x)
.map(y-> y.chars().map(z->z-48).sum())
.forEach(System.out::println);
As pointed out by JBNizet, that solution does not do exactly the same thing. It does not throw an exception if any of the strings are not Integers (and works for Strings representing integers larger than Integer.MAX_VALUE).
Also, it returns a positive sum for negative numbers (for which the - sign should probably filtered, for example with .filter(Character::isDigit)
Another approach assuming input are Integers
This more like a "translation" of OP's code to IntStream.generate(). The stream starts with the original integer and subsequent elements are generated by division by 10. The, the elements are mapped to modulo by 10.
int[]ints={1495,34,333333,-13};
IntStream.of(ints)
.map( a-> IntStream.iterate(a,b->b/10) // (1)
.map(c->c%10) // (2)
.limit(10) // (3)
.sum())
.forEach(System.out::println);
(1) for example generates for 1495 the following IntStream:
1495 149 14 1 0 0 ...
(2) map to modulo:
5 9 4 1 0 0 ...
(3) since this is an infinite stream, we need a limit

Note that not only arrays and collections are streamable, character sequences are as well. Now, you can stream over the characters and convert each digit to a numerical value before summing, but the conversion only implies subtracting the same offset ('0') from the character and there is already a basic arithmetic solution for summing the same number a number of times, the multiplication:
Arrays.stream(args)
.map(s -> s.chars().sum()-'0'*s.length())
.forEach(System.out::println);
This is concise and efficient.
In case you need support for negative numbers, you can change it to
Arrays.stream(args)
.map(s -> s.startsWith("-")?
'0'*(s.length()-1)-s.chars().skip(1).sum():
s.chars().sum()-'0'*s.length())
.forEach(System.out::println);

The checksum computation is not a good candidate for a stream-based solution, IMO. The loop through the arguments can be transformed to streams, though:
public class Help {
public static void main(String[] args) {
Arrays.stream(args)
.mapToInt(Integer::parseInt)
.map(Help::toCheckSum)
.forEach(System.out::println);
}
private static int toCheckSum(int number) {
int checksum = 0;
for (int digits = 0; digits < 10; digits++) {
checksum += number % 10;
number /= 10;
}
return checksum;
}
}

Related

Remove all numbers except the first using recursion

Basically what I have to do is to remove all digits and leave the first one. If it's a number under 10 keep that number.
I already made some code but instead of removing all digits following the first, I removed the first digit.
My code:
public static int keepFirstDigit(int num) {
// Can't change anything besides the following code
if(num==0){
return 0;
}
if(num>0){
return num % (int) Math.pow(10, (int) Math.log10(num));
}
return num;
}
If the number is 5, the output should be 5.
If the number is 23 the output should be 2.
If the number is 62363456 the output should be 6.
First, you need to understand what is recursion and how it works.
Recursion means function/method call itself.
in below program removeDigit method calling itself if n is greater than 10 with n = n/10.
try this one.
public class Main {
public static void main(String[] args) {
System.out.println(removeDigit(23219));
}
public static int removeDigit(int n) {
if (Math.abs(n) < 10) {
return n;
}
return removeDigit(n/10);
}
}
for n = 23219
iteration 1
23219 > 10
call removeDigit with n = 23219/10 = 2321
iteration 2
2321 > 10
call removeDigit with n = 2321/10 = 232
iteration 3
232 > 10
call removeDigit with n = 232/10 = 23
iteration 4
23 > 10
call removeDigit with n = 23/10 = 2
iteration 5
2 < 10
So return 2
I am not sure if recursion is the best tool to do it however this should work :
public static int keepFirstDigit(int num) {
//Can't change anything besides the following code
if(num < 10) {
return num;
} else {
return keepFirstDigit(num / 10);
}
}
If num is less then 10 we jest return it. Otherwise we divide num by 10 without the remainder and pass it to recursive method call.
For negative numbers we could change the negative number to positive as this does not affect first digit :
public static int keepFirstDigit(int num) {
num = Math.abs(num);
if(num < 10) {
return num;
} else {
return keepFirstDigit(num / 10);
}
}
We could also do the abs before calling this method and pass it as parameter.
I'm not sure if you need to do it recursiveley but if you don't, I'd do it like this
public static int keepFirstDigit(int num) {
String tempNum = String.valueOf(num).substring(0,1);
return((int) Integer.parseInt(tempNum));
}
but if you do, just use the other examples that have already been posted
This can also be achieved using Strings, maybe think of this:
public static int keepFirstDigit(int num) {
//Can't change anything besides the following code
return Integer.parseInt((num+"").charAt(0)+"");
}
Based on #Pankaj Singh and #michalk answer, here is a working, verifiable solution in Javascript.
It also handle negative and null values.
Run it to see output and results.
(Probably not the fastest, shortest way though)
Result for 0 -> 0
Result for 10 -> 1
Result for -10 -> -1
Result for 9.9999 -> 9
Result for 1.57 -> 1
Result for 23 -> 2
Result for 34.5 -> 3
Result for 5678848 -> 5
Result for -3.14159 -> -3
Result for -28.123 -> -2
// Define a function doing the job
// Take an object as argument, not a number (for updating purpose)
const getFirstDigit = (obj) => {
// Ensure argument is valid
if (!obj || !obj.count) {
return;
}
if ((obj.count >= 0 && obj.count < 10)
/* handle negatives */
|| (obj.count <= 0 && obj.count > -10)) {
// Ensure it is an integer
obj.count = parseInt(obj.count);
} else {
// Divide by ten: update obj.count
obj.count = parseInt(obj.count / 10);
// Recursion: call again since number is greater or equals than 10
getFirstDigit(obj);
}
}
// At the end of recursion stack, obj.count will be an integer < 10 == the first digit of initial number
// Give some inputs (and negative values)
let numbers = [0, 10, -10, 9.9999, 1.57, 23, 34.50, 5678848, -3.14159, -28.123];
for (index in numbers) {
let input = numbers[index];
// Prepare an object to hold our number
let object = { count: input };
// Call the method by passing an object
// Passing an object rather a primitive Number allow the function to update the object by reference
getFirstDigit(object)
// Retrieve object updated (or not) number
let output = object.count;
console.log(`Result for ${input} -> ${output}`);
}

Extracting a digit from a number ranging from 0 to 99999

I am working at a programm right now where I need to sort an array of numbers ranging from 0 to 99999. In order to do so, one part of the task is to extract the digits from every number of the array, and that can be accomplished by
i = number / digit.
For example, for the number 23456, I am supposed to start by extracting the number 2, which can be done by using
digit = 10000
and calculating
i = 23456 / 10000 = 2.
A recursive call is then supposed to look at the next digit, so in this case we want to get
i = 23456 / digit = 3
and so on. I know that there are certain methods for this, but how can this be done with using only primitves? I already tried to play around with modulo and dividing the digit, but it's not giving any desired result.
Basic Formula
The n-th digit of a non-negative, integral, decimal number can be extracted by the following formula:
digit = ((num % 10^n) / 10^(n-1))
where % represents modulo division, / represents integer division, and ^ represents exponentiation in this example. Note that for this formula, the number is indexed LSD->MSD starting from 1 (not 0).
This formula will also work for non-decimal numbers (e.g. base 16) by changing 10 to the desired base. It will also work for negative numbers provided that absolute value of the final digit is taken. Finally, it can even function to extract the integer digits (but not fractional digits) of a floating point number simply by truncating and casting the floating-point number to an integral number before passing it to this formula.
Recursive Algorithm
So, to recursively extract all of the digits of a number of a certain length in order MSD->LSD, you can use the following Java method:
static public void extractDigits(int num, int length) {
if (length <= 0) { // base case
return;
}
else { // recursive case
int digit = (num % (int)Math.pow(10,length)) / (int)Math.pow(10,length-1);
/* do something with digit here */
extractDigits(num, length-1); // recurse
}
}
This method will never divide by zero.
Note: In order to "do something with digit here," you may need to pass in an additional parameter (e.g. if you want to add the digit to a list).
Optimization
Since your goal is to extract every digit from a number, rather than only one specific digit (as the basic formula assumes), this algorithm may be optimized to extract digits in order LSD->MSD so as to avoid the need for exponentiation at each step. (this approach original given here by #AdityaK ...please upvote them if you use it)
static public void extractDigits(int num) {
if (num == 0) { // base case
return;
}
else { // recursive case
int digit = num % 10;
/* do something with digit here */
extractDigits(num / 10); // recurse
}
}
Note: Any negative number should be converted to a positive number before passing it to this method.
Here's the code to recursively extract numbers from an integer. It will be in reverse order.
import java.util.*;
public class HelloWorld{
static void extractNumbers(int n, List<Integer> l) {
if(n==0)
return;
else {
l.add(n%10);
extractNumbers(n/10, l);
}
}
public static void main(String []args){
List<Integer> result = new ArrayList<Integer>();
extractNumbers(456789,result);
System.out.println(result);
}
}
Hope it helps.
I would do something like this:-
public static void main (String[] args) throws java.lang.Exception
{
// your code goes here
int num=23456;
int numSize=5;
rec(num,numSize);
}
public static void rec(int num, int numSize){
if(numSize==0)
return;
int divideBy=(int)Math.pow(10,(numSize-1));
int out=(int)(num/divideBy);
System.out.println(out);
rec((num-out*divideBy),(numSize-1));
return;
}
See the output from here: http://ideone.com/GR3l5d
This can be easily done by using the for loop by converting the array elements into string.
var arr = [234, 3456, 1234, 45679, 100];
var compare = function(val1, val2) {
return val1 - val2;
};
arr.sort(compare); //sort function
var extract = function(value, index) {
var j = "";
var element = value + "";
for (var i in element) {
var val = element[i];
console.log(parseInt(val)); // this prints the single digits from each array elements
j = j + " " + val;
}
alert(j);
};
arr.forEach(extract); //extract function..

Smallest number from an array

Here is my challenge:
Given a list of non negative integers, arrange them in such a manner that they form the smallest number possible.
The result is going to be very large, hence return the result in the form of a string.
If I consider input array as {20, 1, 5} then all permutations are as below:
2015, 2051, 1205, 1520, 5201, 5120 but as 1205 is smallest hence it should be the result.
Input array {20, 1, 5}
Result: 1205
Here is the method signature:
private String getSmallestNumber(Integer[] nums) {
}
What algorithm should I use?
Similar type of question asked on:
http://www.practice.geeksforgeeks.org/problem-page.php?pid=380
I completed my code but please suggest me better algorithm
private String getSmallestNumber(Integer[] nums) {
String[] arr = new String[nums.length];
for (int i = 0; i < nums.length; i++) {
arr[i] = String.valueOf(nums[i]);
}
Arrays.sort(arr, new Comparator<String>() {
#Override
public int compare(String a, String b) {
return (a + b).compareTo(b + a);
}
});
StringBuilder sb = new StringBuilder();
for (String s : arr) {
sb.append(s);
}
while (sb.charAt(0) == '0' && sb.length() > 1) {
sb.deleteCharAt(0);
}
return sb.toString();
}
The solution is to sort the array using a custom comparator that compares digit-by-digit. In other words, given two numbers, compare the most-significant-digit of the first number to most-significant-digit of the second number. Then compare the second digits, and so on, until you reach the end of one of the numbers, or the digits aren't equal. The number with the lower digit goes first in the answer.
For example 20 comes before 5 because 2 is less than 5. 1000 comes before 99 because 1 is less than 9. 123789 comes before 1239 because 7 is less than 9.
So the trick is to scale the smaller number by multiplying by 10 until both numbers have the same number of digits. For example, given a six-digit number and a four-digit number like
123789
1239
you need to multiply the four-digit number by 100 so both numbers have the same number of digits
123789
123900
Then a simple integer comparison tells you that 123789 comes before 1239. So the code for the comparator looks like this
int compare( int a, int b )
{
int special = b - a; // special case, e.g. 123 and 123000
if ( a <= b ) {
for ( int n = 1; n <= b; n *= 10 )
if ( n > a )
a *= 10;
} else {
for ( int n = 1; n <= a; n *= 10 )
if ( n > b )
b *= 10;
}
if ( a == b )
return special;
else
return a - b;
}
There is a special case where the two numbers end up being equal after scaling. For example, given the numbers 123000 and 123, the correct order is to put 123000 before 123, since that puts the three zeros in the array first, i.e. 123000123 is better than 123123000. Hence a special case is needed to choose the larger number first, if the numbers are equal after scaling. Hence, the need for the variable called special.

How can I count if a specific set of digits are present in an array

Suppose I have a number 123. I need to see if I get all digits 1 through 9, including 0. The number 123 has three digits: 1,2, and 3. Then I multiply it by 2 and get 246 (I get digits 2, 4, 6). Then I multiply it by 3 and I get 369. I keep doing incremental multiplication until I get all digits.
My approach is the following:
public int digitProcessSystem(int N) {
String number = Integer.toString(N);
String [] arr = number.split("");
// List <Integer> arr2 = new ArrayList<>();
for (Integer i = 0; i < arr.length; i++) {
try {
arr2[i] = Integer.parseInt(arr[i]);
} catch (NumberFormatException e) {
}
}
count =0;
boolean contains = IntStream.of(arr2).anyMatch(x -> x == 1|| x==2 ||x == 3|| x==4|| x == 5|| x==6 ||x == 7|| x==8||x == 9|| x==0);
}
I really don't know how can I keep doing the boolean for digits that did not match in the first trail above because I will definitely get any one of the all digits in the above boolean search. How can I get that if some specific digits are present and some are not so that I can multiply the actual number to do the search for the digits that were not found in the first trial; just like the way I defined in the beginning.
You could wrap that into a while loop and include the numbers into a Set. Once the set has the size 10 all digits are present in the number. I´d also suggest to use a long instead of an int or you´ll be getting wrong results or run into an excpetion. Here´s some example code for this:
private static long digitProcessSystem(long N) {
long numberN = N;
String number = Long.toString(N);
// calculate 10 digits number here yet
if (number.length() < 10) {
// using the smallest possible number with each digit
// By using this number we are most likely allmost at the result
// This will increase the performance for small digits heavily.
long divider = 1023456789L / numberN;
numberN *= divider;
}
number = Long.toString(numberN);
String[] arr = number.split("");
Set<String> input = new HashSet<>(Arrays.asList(arr));
while(input.size() != 10){
// add N to number
numberN += N;
// Parse the new number
number = Long.toString(numberN);
// split
arr = number.split("");
// clear set
input.clear();
// Add the new numbers to the set. If it has the size 10 now the loop will stop and return the number.
input.addAll(Arrays.asList(arr));
};
return numberN;
}
public static void main(String[] args) {
System.out.println(digitProcessSystem(123));
}
output:
1023458769
I'm not sure what is your end goal. But you can use a HashSet and do something like this in order to achieve what you are trying to achieve:
public static void main (String[] args) throws Exception {
long number = 123L, counter = 1000000000L / number;
while(digitProcessSystem(number * counter++));
System.out.println("Number: " + number * (counter - 1));
}
public static boolean digitProcessSystem(long input) {
char[] arr = Long.toString(input).toCharArray();
Set<Character> set = new HashSet<>();
for (int i = 0; i < arr.length; i++) {
set.add(arr[i]);
}
return set.size() != 10;
}
Output:
Number: 1023458769
without using java language Facilities and hashset:
private static long digitProcessSystem(long N) {
long numberN = N;
String number = Long.toString(N);
String[] arr = number.split("");;
int arr2=new int[10];
int sum=0;
while(sum != 10){
sum=0;
// add N to number
numberN += N;
// Parse the new number
number = Long.toString(numberN);
// If it doesn´t have 10 digitis continue here yet
if(number.length() < 10) continue;
// split
arr = number.split("");
for(int i=0;i<arr.length;i++){
arr2[arr]=1;
}
for(int i=0;i<10;i++){
sum+=arr2[i];
}
};
return numberN;
}
Generally, if you want to process the characters of a String, don’t do it by splitting the string into substrings. Note that every CharSequence, including String, has the methods chars() and codepoints() allowing to process all characters as IntStream.
To check whether all digits from '0' to '9' are present, we can use chars() (don’t have to think about surrogate pairs) and do it straight-forward, map them to their actual number by subtracting '0', filter out all non-digits (just to be sure), then, map them to an int where the nth bit is set, so we can binary or them all together and check whether all of the lowest ten bits are set:
public static boolean hasAllDigits(String s) {
return s.length()>9 &&
s.chars().map(c -> c-'0').filter(c -> c>=0 && c<=9)
.map(c -> 1 << c).reduce(0, (a,b)->a|b) == 0b1111111111;
}
As a bonus, a length-check is prepended as a String must have at least ten characters to contain all ten digits, so we can short-cut if it hasn’t.
Now, I’m not sure about your actual task. If you just want to iterate until encountering a number having all digits, it’s quite simple:
long number=123;
for(long l = 1, end = Long.MAX_VALUE/number; l < end; l++) {
long candidate = number * l;
if(hasAllDigits(String.valueOf(candidate))) {
System.out.println("found: "+candidate);
return;
}
}
System.out.println("not found within the long range");
But if you want to know when you encountered all digits within the sequence of numbers, we have to adapt the test method and keep the bitset between the iterations:
public static int getDigits(String s) {
return s.chars().map(c -> c-'0').filter(c -> c>=0 && c<=9)
.map(c -> 1 << c).reduce(0, (a,b)->a|b);
}
 
long number=123;
int digits=0;
for(long l = 1, end = Long.MAX_VALUE/number; l < end; l++) {
long candidate=number * l;
int newDigits=digits | getDigits(String.valueOf(candidate));
if(newDigits != digits) {
System.out.printf("pos %10d: %10d%n", l, candidate);
digits=newDigits;
if(digits == 0b1111111111) {
System.out.println("encountered all digits");
break;
}
}
}
if(digits != 0b1111111111) {
System.out.println("did not encounter all digits within the long range");
}
This method will only print numbers of the sequence which have at least one digit not encountered before, so you can easily see which one contributed to the complete set and will see at most ten numbers of the sequence.

calculating factorial using Java 8 IntStream?

I am relatively new in Java 8 and lambda expressions as well as Stream, i can calculate factorial using for loop or recursion. But is there a way to use IntStream to calculate factorial of a number ? I am fine even with factorial in integer range.
I read through IntStream docs here, http://docs.oracle.com/javase/8/docs/api/java/util/stream/IntStream.html and i can see so many methods but not sure which one I can use to calculate factorial.
for example, there is rang method that says,
range(int startInclusive, int endExclusive) Returns a sequential
ordered IntStream from startInclusive (inclusive) to endExclusive
(exclusive) by an incremental step of 1.
so I can use it to provide the range of numbers to IntStream to be multiplied to calculate factorial.
number = 5;
IntStream.range(1, number)
but how to multiply those numbers to get the factorial ?
You can use IntStream::reduce for this job,
int number = 5;
IntStream.rangeClosed(2, number).reduce(1, (x, y) -> x * y)
To get a stream of all infinite factorials, you can do:
class Pair{
final int num;
final int value;
Pair(int num, int value) {
this.num = num;
this.value = value;
}
}
Stream<Pair> allFactorials = Stream.iterate(new Pair(1,1),
x -> new Pair(x.num+1, x.value * (x.num+1)));
allFactorials is a stream of factorials of number starting from 1 to ..... To get factorials of 1 to 10:
allFactorials.limit(10).forEach(x -> System.out.print(x.value+", "));
It prints:
1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800,
Now say you only wish to have a factorial of a particular number then do:
allFactorials.limit(number).reduce((previous, current) -> current).get()
The best part is that you dont recompute again for new numbers but build on history.
With LongStream.range() you can calculate factorial for number less 20. If you need calculate for larger number create stream with BigInteger:
public BigInteger factorial(int number) {
if (number < 20) {
return BigInteger.valueOf(
LongStream.range(1, number + 1).reduce((previous, current) -> previous * current).getAsLong()
);
} else {
BigInteger result = factorial(19);
return result.multiply(Stream.iterate(BigInteger.valueOf(20), i -> i.add(BigInteger.ONE)).limit(number - 19)
.reduce((previous, current) -> previous.multiply(current)).get()
);
}
}
We can solve the question with AtomicInteger like this:
int num = 5;
AtomicInteger sum = new AtomicInteger(1);
IntStream.rangeClosed(2, num).forEach(i -> {
sum.updateAndGet(v -> v * i);
if (i == num) {
System.out.println(sum.get());
}
});
I think we can change the main condition to:
1,vv-1,st with the function reduce.
Maybe we can filter before we did the main rule

Categories

Resources