Java 8 generate stream of integer based on last value - java-8

I need to generate stream of integers that each value is based on the value before according to some math function.
For example - lets say I want to take last number and add 10:
[1, 11, 21, 31, 41, ...]
of course the real function is much more complex.
I tried taking the fibonaci example but couldn't make it work:
Stream.iterate(new long[]{ 1, 1 }, p->new long[]{ p[1], p[0]+p[1] })
.limit(92).forEach(p->System.out.println(p[0]));
I can only start at 1.
This is what I tried doing:
Stream.iterate(new long[]{ 1 }, p-> {p[0], p[0] + 10})
.limit(4).forEach(p->System.out.println(p[0]));

According to Stream#iterate method docs:
Returns an infinite sequential ordered Stream produced by iterative application of a function f to an initial element seed, producing a Stream consisting of seed, f(seed), f(f(seed)), etc.
The first element (position 0) in the Stream will be the provided seed. For n > 0, the element at position n, will be the result of applying the function f to the element at position n - 1.
So, for your example, it should work as follows:
Stream.iterate(1L, x -> x + 10L)
.limit(4)
.forEach(System.out::println); // 1 11 21 31
If your function is too complex, you can abstract it to a method:
private long complexFunction(long value) {
return <very_complex_calculation with value>;
}
long N = 4L;
Stream.iterate(1L, this::complexFunction)
.limit(N)
.forEach(System.out::println);

You can use an AtomicLong to keep another variable when iterating. For the Fibonacci sequence where you would keep the largest of the 2 numbers and in the AtomicLong and the iteration variable would be the smallest. E.g.
AtomicLong fibonacci = new AtomicLong(1);
Stream.iterate(1L, x -> fibonacci.getAndAdd(x))
.limit(10)
.forEach(i -> System.out.println(fibonacci.get()));

if I don't misunderstand you, you want something like this, you needn't any long[]array at all.
LongStream.iterate(1, it -> it + 10).limit(8).forEach(System.out::println);
for the Integers you can using IntStream#interate instead:
// v--- call your math function here
IntStream.iterate(1, it -> math(it, ...)).limit(8).forEach(System.out::println);
OR using LongStream#range instead:
LongStream.range(0,8).map(it -> 10*it + 1).forEach(System.out::println);
Output
[1, 11, 21, 31, 41, 51, 61, 71]

Related

Approaching Dynamic Programming problem / Two restrictions

Given an array A of n integers and k <= n, we want to choose k numbers from this array and split them to pairs, such that the sum of the differences of those pairs (in absolute value) is minimal.
Example: If n = 8 and k = 6 and the array is A = [140, 100, 92, 21, 32, 48, 32, 100], then the optimal answer is 27.
Does someone have an idea?
Where do I start from in this problem?
I'm really bad at DP problems, so I would appreciate an informative answer describing the right approach to solve the problem.
Thanks in advance.
Sort elements. Now pairs ought to be made only with neighbors (for cases like 10,20,20,30 pairing 10/20 + 20/30 gives the same result as 10/30 + 20/20, for cases like 10,14,20 pair 10/20 is worse than 10/14 or 14/10)
Walk through array.
If pair is opened with the last element, we have the only possibility - close that pair with current element
If there is no opened pair and number of closed pairs is less than k/2, we have two possibilities - start pair or omit current element (if number of elements in the rest of array is larger than we must use), and we have to choose the best result from these cases.
So we can build recursion and then transform it into DP (code below is not DP yet, it builds full solution tree).
A = [140, 100, 92, 21, 32, 48, 32, 100]
n = len(A)
k = 6
def best(idx, openstate, pairsleft):
if pairsleft > (n - idx + 1)//2:
return 10000000
if pairsleft == 0:
return 0
if openstate:
return abs(A[idx] - A[idx-1]) + best(idx + 1, False, pairsleft - 1)
else:
return(min(best(idx + 1, True, pairsleft), best(idx + 1, False, pairsleft)))
A.sort()
print(best(0, False, k//2))
>> 27

Find a number in a list of numbers using Java8 sterams

I have a list of numbers
List<Integer> tensOfMinutes = Arrays.asList(10, 20, 30, 40, 50, 60);
I'm trying to determine if an input int Integer minutes; is between any two members of the array above.
Example: for an input Integer minutes = 23; I expect to get 20 as an answer.
Any ideas for how to accomplish this while iterating a stream of tensOfMinutes ?
You can do it this way:
List<Integer> l = Arrays.asList(10, 20, 30, 40, 50, 60)
.stream()
.filter( (i) -> i<23 )
.collect(Collectors.toList());
System.out.println( l.get( l.size() - 1 ) );
You filter out all elements bigger than 23 and you print the last one of the remaining elements.
It would have been easier with the dropWhile function that we have in Java 9, Scala and Haskell:
https://docs.oracle.com/javase/9/docs/api/java/util/stream/Stream.html#dropWhile-java.util.function.Predicate-
Improved version by Holger
Stream<Integer> stream = Arrays.asList(10, 20, 30, 40, 50, 60).stream();
stream.filter( i -> i<23 )
.reduce( (a,b) -> b )
.ifPresent(System.out::println);
You can see the (a,b) -> b lambda used to ger the last element and the ifPresent method used to make it error safe.
List list=IntStream.of(10,20,6,7,81).boxed().collect(Collectors.toList());
You will want the number before the first larger number so try this:
int previous=0
for(Integer number : tensOfMinutes)
if(number<=numberToFind)
previous=number;
You will cycle through all numbers and remember the last one that was smaller or equal to the number youre searching for in the variable previous. This expects the list to be sorted in ascending order. I don't know the exact specs of the integer class but that's the way of approach

How to detect if a repeating pattern exists

My question isn't language specific... I would probably implement this in C# or Python unless there is a specific feature of a language that helps me get what I am looking for.
Is there some sort of algorithm that anyone knows of that can help me determine if a list of numbers contains a repeating pattern?
Let's say I have a several lists of numbers...
[12, 4, 5, 7, 1, 2]
[1, 2, 3, 1, 2, 3, 1, 2, 3]
[1, 1, 1, 1, 1, 1]
[ 1, 2, 4, 12, 13, 1, 2, 4, 12, 13]
I need to detect if there is a repeating pattern in each list... For example, list 1 returns false, but and lists 2, 3, and 4 return true.
I was thinking maybe taking a count of each value that appears in the list and if val 1 == val 2 == val n... then that would do it. Any better ideas?
You want to look at the autocorrelation of the signal. Autocorrelation basically does a convolution of the signal with itself. When a you iteratively slide one signal across another, and there is a repeating pattern, the output will resonate strongly.
The second and fourth strings are periodic; I'm going to assume you're looking for an algorithm for detecting periodic strings. Most fast string matching algorithms need to find periods of strings in order to compute their shifting rules.
Knuth-Morris-Pratt's preprocessing, for instance, computes, for every prefix P[0..k] of the pattern P, the length SP[k] of the longest proper suffix P[s..k] of P[0..k] that exactly matches the prefix P[0..(k-s)]. If SP[k] < k/2, then P[0..k] is aperiodic; otherwise, it is a prefix of a string with period k - SP[k].
One option would be to look at compression algorithms, some of those rely on finding repeating patterns and replacing them with another symbol. In your case you simply need the part that identifies the pattern. You may find that it is similar to the method that you've described already though
Assuming that your "repeating pattern" is always repeated in full, like your sample data suggests, you could just think of your array as a bunch of repeating arrays of equal length. Meaning:
[1, 2, 3, 1, 2, 3, 1, 2, 3] is the same as [1, 2, 3] repeated three times.
This means that you could just check to see if every x value in the array is equal to each other. So:
array[0] == array[3] == array[6]
array[1] == array[4] == array[7]
array[2] == array[5] == array[8]
Since you don't know the length of the repeated pattern, you'd just have to try all possible lengths until you found a pattern or ran out of possible shorter arrays. I'm sure there are optimizations that can be added to the following, but it works (assuming I understand the question correctly, of course).
static void Main(string[] args)
{
int[] array1 = {12, 4, 5, 7, 1, 2};
int[] array2 = {1, 2, 3, 1, 2, 3, 1, 2, 3};
int[] array3 = {1, 1, 1, 1, 1, 1 };
int[] array4 = {1, 2, 4, 12, 13, 1, 2, 4, 12, 13 };
Console.WriteLine(splitMethod(array1));
Console.WriteLine(splitMethod(array2));
Console.WriteLine(splitMethod(array3));
Console.WriteLine(splitMethod(array4));
Console.ReadLine();
}
static bool splitMethod(int[] array)
{
for(int patternLength = 1; patternLength <= array.Length/2; patternLength++)
{
// if the pattern length doesn't divide the length of the array evenly,
// then we can't have a pattern of that length.
if(array.Length % patternLength != 0)
{
continue;
}
// To check if every x value is equal, we need to give a start index
// To begin our comparisons at.
// We'll start at index 0 and check it against 0+x, 0+x+x, 0+x+x+x, etc.
// Then we'll use index 1 and check it against 1+x, 1+x+x, 1+x+x+x, etc.
// Then... etc.
// If we find that every x value starting at a given start index aren't
// equal, then we'll continue to the next pattern length.
// We'll assume our patternLength will produce a pattern and let
// our test determines if we don't have a pattern.
bool foundPattern = true;
for (int startIndex = 0; startIndex < patternLength; startIndex++)
{
if (!everyXValueEqual(array, patternLength, startIndex))
{
foundPattern = false;
break;
}
}
if (foundPattern)
{
return true;
}
}
return false;
}
static bool everyXValueEqual(int[] array, int x, int startIndex)
{
// if the next index we want to compare against is outside the bounds of the array
// we've done all the matching we can for a pattern of length x.
if (startIndex+x > array.Length-1)
return true;
// if the value at starIndex equals the value at startIndex + x
// we can go on to test values at startIndex + x and startIndex + x + x
if (array[startIndex] == array[startIndex + x])
return everyXValueEqual(array, x, startIndex + x);
return false;
}
Simple pattern recognition is the task of compression algorithms. Depending on the type of input and the type of patterns you're looking for the algorithm of choice may be very different - just consider that any file is an array of bytes and there are many types of compression for various types of data. Lossless compression finds exact patterns that repeat and lossy compression - approximate patterns where the approximation is limited by some "real-world" consideration.
In your case you can apply a pseudo zip compression where you start filling up a list of encountered sequences
here's a pseudo suggestion:
//C#-based pseudo code
int[] input = GetInputData();
var encounters = new Dictionary<ItemCount<int[],int>>();// the string and the number of times it's found
int from = 0;
for(int to=0; to<input.Length; i++){
for (int j = from; j<=i; j++){ // for each substring between 'from' and 'i'
if (encounters.ContainsKey(input.SubArray(j,i)){
if (j==from) from++; // if the entire substring already exists - move the starting point
encounters[input.SubArray(j,i)] += 1; // increase the count where the substring already exists
} else {
// consider: if (MeetsSomeMinimumRequirements(input.SubArray(j,i))
encounters.Add(input.SubArray(j,i),1); //add a new pattern
}
}
}
Output(encounters.Where(itemValue => itemValue.Value>1); // show the patterns found more than once
I haven't debugged the sample above, so use it just as a starting point. The core idea is that you'd have an encounters list where various substrings are collected and counted, the most frequent will have highest Value in the end.
You can alter the algorithm above by storing some function of the substrings instead of the entire substring or add some minimum requirements such as minimum length etc. Too many options, complete discussion is not possible within a post.
Since you're looking for repeated patterns, you could force your array into a string and run a regular expression against it. This being my second answer, I'm just playing around here.
static Regex regex = new Regex(#"^(?<main>(?<v>;\d+)+?)(\k<main>)+$", RegexOptions.Compiled);
static bool regexMethod(int[] array)
{
string a = ";" + string.Join(";", array);
return regex.IsMatch(a);
}
The regular expression is
(?<v>;\d+) - A group named "v" which matches a semicolon (the delimiter in this case) and 1 or more digits
(?<main>(?<v>;\d+)+?) - a group named "main" which matches the "v" group 1 or more times, but the least number of times it can to satisfy the regex.
(\k<main>)+ - matches the text that the "main" group matched 1 or more times
^ ... $ - these anchor the ends of the pattern to the ends of the string.

Allocate an array of integers proportionally compensating for rounding errors

I have an array of non-negative values. I want to build an array of values who's sum is 20 so that they are proportional to the first array.
This would be an easy problem, except that I want the proportional array to sum to exactly
20, compensating for any rounding error.
For example, the array
input = [400, 400, 0, 0, 100, 50, 50]
would yield
output = [8, 8, 0, 0, 2, 1, 1]
sum(output) = 20
However, most cases are going to have a lot of rounding errors, like
input = [3, 3, 3, 3, 3, 3, 18]
naively yields
output = [1, 1, 1, 1, 1, 1, 10]
sum(output) = 16 (ouch)
Is there a good way to apportion the output array so that it adds up to 20 every time?
There's a very simple answer to this question: I've done it many times. After each assignment into the new array, you reduce the values you're working with as follows:
Call the first array A, and the new, proportional array B (which starts out empty).
Call the sum of A elements T
Call the desired sum S.
For each element of the array (i) do the following:
a. B[i] = round(A[i] / T * S). (rounding to nearest integer, penny or whatever is required)
b. T = T - A[i]
c. S = S - B[i]
That's it! Easy to implement in any programming language or in a spreadsheet.
The solution is optimal in that the resulting array's elements will never be more than 1 away from their ideal, non-rounded values. Let's demonstrate with your example:
T = 36, S = 20. B[1] = round(A[1] / T * S) = 2. (ideally, 1.666....)
T = 33, S = 18. B[2] = round(A[2] / T * S) = 2. (ideally, 1.666....)
T = 30, S = 16. B[3] = round(A[3] / T * S) = 2. (ideally, 1.666....)
T = 27, S = 14. B[4] = round(A[4] / T * S) = 2. (ideally, 1.666....)
T = 24, S = 12. B[5] = round(A[5] / T * S) = 2. (ideally, 1.666....)
T = 21, S = 10. B[6] = round(A[6] / T * S) = 1. (ideally, 1.666....)
T = 18, S = 9. B[7] = round(A[7] / T * S) = 9. (ideally, 10)
Notice that comparing every value in B with it's ideal value in parentheses, the difference is never more than 1.
It's also interesting to note that rearranging the elements in the array can result in different corresponding values in the resulting array. I've found that arranging the elements in ascending order is best, because it results in the smallest average percentage difference between actual and ideal.
Your problem is similar to a proportional representation where you want to share N seats (in your case 20) among parties proportionnaly to the votes they obtain, in your case [3, 3, 3, 3, 3, 3, 18]
There are several methods used in different countries to handle the rounding problem. My code below uses the Hagenbach-Bischoff quota method used in Switzerland, which basically allocates the seats remaining after an integer division by (N+1) to parties which have the highest remainder:
def proportional(nseats,votes):
"""assign n seats proportionaly to votes using Hagenbach-Bischoff quota
:param nseats: int number of seats to assign
:param votes: iterable of int or float weighting each party
:result: list of ints seats allocated to each party
"""
quota=sum(votes)/(1.+nseats) #force float
frac=[vote/quota for vote in votes]
res=[int(f) for f in frac]
n=nseats-sum(res) #number of seats remaining to allocate
if n==0: return res #done
if n<0: return [min(x,nseats) for x in res] # see siamii's comment
#give the remaining seats to the n parties with the largest remainder
remainders=[ai-bi for ai,bi in zip(frac,res)]
limit=sorted(remainders,reverse=True)[n-1]
#n parties with remainter larger than limit get an extra seat
for i,r in enumerate(remainders):
if r>=limit:
res[i]+=1
n-=1 # attempt to handle perfect equality
if n==0: return res #done
raise #should never happen
However this method doesn't always give the same number of seats to parties with perfect equality as in your case:
proportional(20,[3, 3, 3, 3, 3, 3, 18])
[2,2,2,2,1,1,10]
You have set 3 incompatible requirements. An integer-valued array proportional to [1,1,1] cannot be made to sum to exactly 20. You must choose to break one of the "sum to exactly 20", "proportional to input", and "integer values" requirements.
If you choose to break the requirement for integer values, then use floating point or rational numbers. If you choose to break the exact sum requirement, then you've already solved the problem. Choosing to break proportionality is a little trickier. One approach you might take is to figure out how far off your sum is, and then distribute corrections randomly through the output array. For example, if your input is:
[1, 1, 1]
then you could first make it sum as well as possible while still being proportional:
[7, 7, 7]
and since 20 - (7+7+7) = -1, choose one element to decrement at random:
[7, 6, 7]
If the error was 4, you would choose four elements to increment.
A naïve solution that doesn't perform well, but will provide the right result...
Write an iterator that given an array with eight integers (candidate) and the input array, output the index of the element that is farthest away from being proportional to the others (pseudocode):
function next_index(candidate, input)
// Calculate weights
for i in 1 .. 8
w[i] = candidate[i] / input[i]
end for
// find the smallest weight
min = 0
min_index = 0
for i in 1 .. 8
if w[i] < min then
min = w[i]
min_index = i
end if
end for
return min_index
end function
Then just do this
result = [0, 0, 0, 0, 0, 0, 0, 0]
result[next_index(result, input)]++ for 1 .. 20
If there is no optimal solution, it'll skew towards the beginning of the array.
Using the approach above, you can reduce the number of iterations by rounding down (as you did in your example) and then just use the approach above to add what has been left out due to rounding errors:
result = <<approach using rounding down>>
while sum(result) < 20
result[next_index(result, input)]++
So the answers and comments above were helpful... particularly the decreasing sum comment from #Frederik.
The solution I came up with takes advantage of the fact that for an input array v, sum(v_i * 20) is divisible by sum(v). So for each value in v, I mulitply by 20 and divide by the sum. I keep the quotient, and accumulate the remainder. Whenever the accumulator is greater than sum(v), I add one to the value. That way I'm guaranteed that all the remainders get rolled into the results.
Is that legible? Here's the implementation in Python:
def proportion(values, total):
# set up by getting the sum of the values and starting
# with an empty result list and accumulator
sum_values = sum(values)
new_values = []
acc = 0
for v in values:
# for each value, find quotient and remainder
q, r = divmod(v * total, sum_values)
if acc + r < sum_values:
# if the accumlator plus remainder is too small, just add and move on
acc += r
else:
# we've accumulated enough to go over sum(values), so add 1 to result
if acc > r:
# add to previous
new_values[-1] += 1
else:
# add to current
q += 1
acc -= sum_values - r
# save the new value
new_values.append(q)
# accumulator is guaranteed to be zero at the end
print new_values, sum_values, acc
return new_values
(I added an enhancement that if the accumulator > remainder, I increment the previous value instead of the current value)

Problem coming up with an array function

Let's say I have an increasing sequence of integers: seq = [1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 4 ... ] not guaranteed to have exactly the same number of each integer but guaranteed to be increasing by 1.
Is there a function F that can operate on this sequence whereby F(seq, x) would give me all 1's when an integer in the sequence equals x and all other integers would be 0.
For example:
t = [1, 1, 1, 1, 2, 2, 3, 3, 3, 4]
F(t, 2) = [0, 0, 0, 0, 1, 1, 0, 0, 0, 0]
EDIT: I probably should have made it more clear. Is there a solution where I can do some algebraic operations on the entire array to get the desired result, without iterating over it?
So, I'm wondering if I can do something like: F(t, x) = t op x ?
In Python (t is a numpy.array) it could be:
(t * -1) % x or something...
EDIT2: I found out that the identity function I(t[i] == x) is acceptable to use as an algebraic operation. Sorry, I did not know about identity functions.
There's a very simple solution to this that doesn't require most of the restrictions you place upon the domain. Just create a new array of the same size, loop through and test for equality between the element in the array and the value you want to compare against. When they're the same, set the corresponding element in the new array to 1. Otherwise, set it to 0. The actual implementation depends on the language you're working with, but should be fairly simple.
If we do take into account your domain, you can introduce a couple of optimisations. If you start with an array of zeroes, you only need to fill in the ones. You know you don't need to start checking until the (n - 1)th element, where n is the value you're comparing against, because there must be at least one of the numbers 1 to n in increasing order. If you don't have to start at 1, you can still start at (n - start). Similarly, if you haven't come across it at array[n - 1], you can jump n - array[n - 1] more elements. You can repeat this, skipping most of the elements, as much as you need to until you either hit the right value or the end of the list (if it's not in there at all).
After you finish dealing with the value you want, there's no need to check the rest of the array, as you know it'll always be increasing. So you can stop early too.
A simple method (with C# code) is to simply iterate over the sequence and test it, returning either 1 or 0.
foreach (int element in sequence)
if (element == myValue)
yield return 1;
else
yield return 0;
(Written using LINQ)
sequence.Select(elem => elem == myValue ? 1 : 0);
A dichotomy algorithm can quickly locate the range where t[x] = n making such a function of sub-linear complexity in time.
Are you asking for a readymade c++, java API or are you asking for an algorithm? Or is this homework question?
I see the simple algorithm for scanning the array from start to end and comparing with each. If equals then put as 1 else put as 0. Anyway to put the elements in the array you will have to access each element of the new array atleast one. So overall approach will be O(1).
You can certainly reduce the comparison by starting a binary search. Once you find the required number then simply go forward and backward searching for the same number.
Here is a java method which returns a new array.
public static int[] sequence(int[] seq, int number)
{
int[] newSequence = new int[seq.length];
for ( int index = 0; index < seq.length; index++ )
{
if ( seq[index] == number )
{
newSequence[index] = 1;
}
else
{
newSequence[index] = 0;
}
}
return newSequence;
}
I would initialize an array of zeroes, then do a binary search on the sequence to find the first element that fits your criteria, and only start setting 1's from there. As soon as you have a not equal condition, stop.
Here is a way to do it in O(log n)
>>> from bisect import bisect
>>> def f(t, n):
... i = bisect(t,n-1)
... j = bisect(t,n,lo=i) - i
... return [0]*i+[1]*j+[0]*(len(t)-j-i)
...
...
>>> t = [1, 1, 1, 1, 2, 2, 3, 3, 3, 4]
>>> print f(t, 2)
[0, 0, 0, 0, 1, 1, 0, 0, 0, 0]

Resources