Merge values of objects with ImmutableJS - immutability

I have a List of several objects. All with the same keys. I'm trying to find an efficient way to reduce the values into a single object.
var list = Immutable.fromJS([{
first: 3,
second: 4,
third: 2
}, {
first: 7,
second, 6,
third: 8
}]);
Wanting to return:
{first: 10,
second: 10,
third: 10}
I'm really just trying to find a way to merge an object, but add the values instead of replacing them. Hope that makes sense.

take the outer array as List and while running reduce, merge inner Maps
list.reduce(function(a, b){
return a.
mergeWith(function(x, y){
return x + y;
}, b)
}).toJS()

Related

Java 8 generate stream of integer based on last value

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]

Algorithm to generate all multiset size-n partitions

I've been trying to figure out a way to generate all distinct size-n partitions of a multiset, but so far have come up empty handed. First let me show what I'm trying to archieve.
Let's say we have an input vector of uint32_t:
std::vector<uint32_t> input = {1, 1, 2, 2}
An let's say we want to create all distinct 2-size partitions. There's only two of these, namely:
[[1, 1], [2, 2]], [[1, 2], [1, 2]]
Note that order does not matter, i.e. all of the following are duplicate, incorrect solutions.
Duplicate because order within a permutation group does not matter:
[[2, 1], [1, 2]]
Duplicate because order of groups does not matter:
[[2, 2], [1, 1]]
Not homework of some kind BTW. I encountered this while coding something at work, but by now it is out of personal interest that I'd like to know how to deal with this. The parameters for the work-related problem were small enough that generating a couple thousand duplicate solutions didn't really matter.
Current solution (generates duplicates)
In order to illustrate that I'm not just asking without having tried to come up with a solution, let me try to explain my current algorithm (which generates duplicate solutions when used with multisets).
It works as follows: the state has a bitset with n bits set to 1 for each partition block. The length of the bitsets is size(input) - n * index_block(), e.g. if the input vector has 8 elements and n = 2, then the first partition block uses an 8-bit bitset with 2 bits set to 1, the next partition block uses a 6-bit bitset with 2 bits set to 1, etc.
A partition is created from these bitsets by iterating over each bitset in order and extracting the elements of the input vector with indices equal to the position of 1-bits in the current bitset.
In order to generate the next partition, I iterate over the bitsets in reverse order. The next bitset permutation is calculated (using a reverse of Gosper's hack). If the first bit in the current bitset is not set (i.e. vector index 0 not selected), then that bitset is reset to its starting state. Enforcing that the first bit is always set prevents generating duplicates when creating size-n set partitions (duplicates of the 2nd kind shown above). If the current bitset is equal to its starting value, this step is then repeated for the previous (longer) bitset.
This works great (and very fast) for sets. However, when used with multisets it generates duplicate solutions, since it is unaware that both elements appear more than once in the input vector. Here's some example output:
std::vector<uint32_t> input = {1, 2, 3, 4};
printAllSolutions(myCurrentAlgo(input, 2));
=> [[2, 1], [4, 3]], [[3, 1], [4, 2]], [[4, 1], [3, 2]]
std::vector<uint32_t> input = {1, 1, 2, 2};
printAllSolutions(myCurrentAlgo(input, 2));
=> [[1, 1], [2, 2]], [[2, 1], [2, 1]], [[2, 1], [2, 1]]
That last (duplicate) solution is generated simply because the algorithm is unaware of duplicates in the input, it generates the exact same internal states (i.e. which indices to select) in both examples.
Wanted solution
I guess it's pretty clear by now what I'm trying to end up with. Just for the sake of completeness, it would look somewhat as follows:
std::vector<uint32_t> multiset = {1, 1, 2, 2};
MagicClass myGenerator(multiset, 2);
do {
std::vector<std::vector<uint32_t> > nextSolution = myGenerator.getCurrent();
std::cout << nextSolution << std::endl;
} while (myGenerator.calcNext());
=> [[1, 1], [2, 2]]
[[1, 2], [1, 2]]
I.e. the code would work somewhat like std::next_permutation, informing that is has generated all solutions and has ended back at the "first" solution (for whatever definition of first you want to use, probably lexicographically, but doesn't need to be).
The closest related algorithm I found is Algorithm M from Knuth's The Art of Computer Programming, Volume 4 Part 1, section 7.2.1.5 (p. 430). However, that generates all possible multiset partitions. There is also an exercise in the book (7.2.1.5.69, solution on p. 778) about how to modify Alg. M in order to generate only solutions with at most r partitions. However, that still allows partitions of different sizes (e.g. [[1, 2, 2], [1]] would be a valid output for r = 2).
Any ideas/tricks/existing algorithms on how to go about this? Note that the solution should be efficient, i.e. keeping track of all previously generated solutions, figuring out if the currently generated one is a permutation and if so skipping it, is infeasible because of the rate by which the solution space explodes for longer inputs with more duplicates.
A recursive algorithm to distribute the elements one-by-one could be based on a few simple rules:
Start by sorting or counting the different elements; they don't have to be in any particular order, you just want to group identical elements together. (This step will simplify some of the following steps, but could be skipped.)
{A,B,D,C,C,D,B,A,C} -> {A,A,B,B,D,D,C,C,C}
Start with an empty solution, and insert the elements one by one, using the following rules:
{ , , } { , , } { , , }
Before inserting an element, find the duplicate blocks, e.g.:
{A, , } { , , } { , , }
^dup^
{A, , } {A, , } {A, , }
^dup^ ^dup^
Insert the element into every non-duplicate block with available space:
partial solution: {A, , } {A, , } { , , }
^dup^
insert element B: {A,B, } {A, , } { , , }
{A, , } {A, , } {B, , }
If an identical element is already present, don't put the new element before it:
partial solution: {A, , } {B, , } { , , }
insert another B: {A,B, } {B, , } { , , } <- ILLEGAL
{A, , } {B,B, } { , , } <- OK
{A, , } {B, , } {B, , } <- OK
When inserting an element of which there are another N identical elements, make sure to leave N open spots after the current element:
partial solution: {A, , } {A, , } {B,B, }
insert first D: {A,D, } {A, , } {B,B, } <- OK
{A, , } {A, , } {B,B,D} <- ILLEGAL (NO SPACE FOR 2ND D)
The last group of identical elements can be inserted in one go:
partial solution: {A,A, } {B,B,D} {D, , }
insert C,C,C: {A,A,C} {B,B,D} {D,C,C}
So the algorithm would be something like this:
// PREPARATION
Sort or group input. // {A,B,D,C,C,D,B,A,C} -> {A,A,B,B,D,D,C,C,C}
Create empty partial solution. // { , , } { , , } { , , }
Start recursion with empty partial solution and index at start of input.
// RECURSION
Receive partial solution, index, group size and last-used block.
If group size is zero:
Find group size of identical elements in input, starting at index.
Set last-used block to first block.
Find empty places in partial solution, starting at last-used block.
If index is at last group in input:
Fill empty spaces with elements of last group.
Store complete solution.
Return from recursion.
Mark duplicate blocks in partial solution.
For each block in partial solution, starting at last-used block:
If current block is not a duplicate, and has empty places,
and the places left in current and later blocks is not less than the group size:
Insert element into copy of partial solution.
Recurse with copy, index + 1, group size - 1, current block.
I tested a simple JavaScript implementation of this algorithm, and it gives the correct output.
Here's my pencil and paper algorithm:
Describe the multiset in item quantities, e.g., {(1,2),(2,2)}
f(multiset,result):
if the multiset is empty:
return result
otherwise:
call f again with each unique distribution of one element added to result and
removed from the multiset state
Example:
{(1,2),(2,2),(3,2)} n = 2
11 -> 11 22 -> 11 22 33
11 2 2 -> 11 23 23
1 1 -> 12 12 -> 12 12 33
12 1 2 -> 12 13 23
Example:
{(1,2),(2,2),(3,2)} n = 3
11 -> 112 2 -> 112 233
11 22 -> 113 223
1 1 -> 122 1 -> 122 133
12 12 -> 123 123
Let's solve the problem commented below by m69 of dealing with potential duplicate distribution:
{A,B,B,C,C,D,D,D,D}
We've reached {A, , }{B, , }{B, , }, have 2 C's to distribute
and we'd like to avoid `ac bc b` generated along with `ac b bc`.
Because our generation in the level just above is ordered, the series of identical
counts will be continuous. When a series of identical counts is encountered, make
the assignment for the whole block of identical counts (rather than each one),
and partition that contribution in descending parts; for example,
| identical |
ac b b
ac bc b // descending parts [1,0]
Example of longer block:
| identical block | descending parts
ac bcccc b b b // [4,0,0,0]
ac bccc bc b b // [3,1,0,0]
ac bcc bcc b b // [2,2,0,0]
...
Here's a working solution that makes use of the next_combination function presented by Hervé Brönnimann in N2639. The comments should make it pretty self-explanatory. The "herve/combinatorics.hpp" file contains the code listed in N2639 inside the herve namespace. It's in C++11/14, converting to an older standard should be pretty trivial.
Note that I only quickly tested the solution. Also, I extracted it from a class-based implementation just a couple of minutes ago, so some extra bugs might have crept in. A quick initial test seems to confirm it works, but there might be corner cases for which it won't.
#include <cstdint>
#include <iterator>
#include "herve/combinatorics.hpp"
template <typename BidirIter>
bool next_combination_partition (BidirIter const & startIt,
BidirIter const & endIt, uint32_t const groupSize) {
// Typedefs
using tDiff = typename std::iterator_traits<BidirIter>::difference_type;
// Skip the last partition, because is consists of the remaining elements.
// Thus if there's 2 groups or less, the start should be at position 0.
tDiff const totalLength = std::distance(startIt, endIt);
uint32_t const numTotalGroups = std::max(static_cast<uint32_t>((totalLength - 1) / groupSize + 1), 2u);
uint32_t curBegin = (numTotalGroups - 2) * groupSize;
uint32_t const lastGroupBegin = curBegin - 1;
uint32_t curMid = curBegin + groupSize;
bool atStart = (totalLength != 0);
// Iterate over combinations from back of list to front. If a combination ends
// up at its starting value, update the previous one as well.
for (; (curMid != 0) && (atStart);
curMid = curBegin, curBegin -= groupSize) {
// To prevent duplicates, first element of each combination partition needs
// to be fixed. So move start iterator to the next element. This is not true
// for the starting (2nd to last) group though.
uint32_t const startIndex = std::min(curBegin + 1, lastGroupBegin + 1);
auto const iterStart = std::next(startIt, startIndex);
auto const iterMid = std::next(startIt, curMid);
atStart = !herve::next_combination(iterStart, iterMid, endIt);
}
return !atStart;
}
Edit Below is my quickly thrown together test code ("combopart.hpp" obviously being the file containing the above function).
#include "combopart.hpp"
#include <algorithm>
#include <cstdint>
#include <iostream>
#include <iterator>
#include <vector>
int main (int argc, char* argv[]) {
uint32_t const groupSize = 2;
std::vector<uint32_t> v;
v = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
v = {0, 0, 0, 1, 1, 1, 2, 2, 2, 3};
v = {1, 1, 2, 2};
// Make sure contents are sorted
std::sort(v.begin(), v.end());
uint64_t count = 0;
do {
++count;
std::cout << "[ ";
uint32_t elemCount = 0;
for (auto it = v.begin(); it != v.end(); ++it) {
std::cout << *it << " ";
elemCount++;
if ((elemCount % groupSize == 0) && (it != std::prev(v.end()))) {
std::cout << "| ";
}
}
std::cout << "]" << std::endl;
} while (next_combination_partition(v.begin(), v.end(), groupSize));
std::cout << std::endl << "# elements: " << v.size() << " - group size: " <<
groupSize << " - # combination partitions: " << count << std::endl;
return 0;
}
Edit 2 Improved algorithm. Replaced early exit branch with combination of conditional move (using std::max) and setting atStart boolean to false. Untested though, be warned.
Edit 3 Needed an extra modification so as not to "fix" the first element in the 2nd to last partition. The additional code should compile as a conditional move, so there should be no branching cost associated with it.
P.S.: I am aware that the code to generate combinations by #Howard Hinnant (available at https://howardhinnant.github.io/combinations.html) is much faster than the one by Hervé Brönnimann. However, that code can not handle duplicates in the input (because as far as I can see, it never even dereferences an iterator), which my problem explicitly requires. On the other hand, if you know for sure your input won't contain duplicates, it is definitely the code you want use with my function above.

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.

Get index of first list and use it in another list

I have two lists:
List1 has values like: "A, A, A, A, B, B, B, B, C, C, C, C, C... so on
List2 has values like: "0, 1, 2, 2, 1.1, 1.2, 1.3, 4, 4, 4, 4.... so on
I want to get index of List1 with values of lets say B and find corrosponding values in List2.
What i am doing is getting start and end index of List1 where value is B. Than looping through list2 for those indexes and getting values. This seems like too much work and lot of overhead. Is there a better way of doing this using linq?
I used this: var list1Values = list1.FindAll(x => x.Contains("B")); This gives me values from B i am stuck after this like how can i get corresponding values from list2 after this? As findAll dont even give index. One thought is to loop through index of list1Values and get list2 values but dont think that is right way to do it.
Provided both lists have the same length, you could use Zip to pair up the corresponding items from both sequences:
var target = "B";
var result = list1.Zip(list2, (x,y) => Tuple.Create(x,y))
.Where(o => o.Item1 == target);
foreach(var item in result)
{
Console.WriteLine(item.Item2);
}
I used a Tuple, so Item1 is the letter from list1 and Item2 is the corresponding item in list2. Of course you could've used an anonymous type and given it a more meaningful name instead.
UPDATE: I just noticed that you tagged the question with C#-3.0. In that case, use the solution below. Zip and Tuple were introduced in .NET 4.0. The solution below uses the Select method, which was available in .NET 3.5. Both solutions use LINQ, so you need to add the namespace: using System.Linq;
Another solution is to use the overloaded Select method to get the indices of the target letter, then grabbing the items from the second list based on those indices.
var target = "B";
var targetIndices = list1.Select((o, i) => new { Value = o, Index = i })
.Where(o => o.Value == target);
var query = targetIndices.Select(o => list2[o.Index]);
foreach(var item in query)
{
Console.WriteLine(item);
}

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