finding onsets (and offsets) of number sequence - string

given the following cell array:
strings = {'str1', 'str2', 'str2', 'str1', 'str2', 'str2', 'str1', 'str1', 'str2'};
I want to find the onsets and offsets (first occurrence and last occurrence) of a particular value. For example, the following are the onsets and offsets for 'str1':
onset_str1 = [1, 4, 7, ];
offset_str1 = [1, 4, 8, ];
And here are the on- and offsets for 'str2':
onset_str2 = [2, 5, 9];
offset_str2 = [3, 6, 9];
Currently I do something like this:
[blub, ia, ic] = unique(strings, 'first');
all_str1 = find(ic == 1); % 1 4 7 8
all_str2 = find(ic == 2); % 2 3 5 6 9
Using all_str1 and all_str2 I would then look for consecutive values (using diff for example) and determine that way the on and offsets. However this kind of implementation feels 'hackish' to me.
What other ways are there to extract the on and offsets in my sequence efficiently?

[blub, ia, ic] = unique(strings, 'first');
ok, but next up, just use logicals and find to find the rising/falling edges:
N = numel(blub); % number of unique strings found
str_onsets=cell(N,1);
str_offsets=cell(N,1);
for ii=1:N
x=ic==ii;
str_onsets{ii} = find([true ~x(1:end-1)] & x);
str_offsets{ii}= find(x & [~x(2:end) true]);
end
or strfind if that's more clear to understand to you:
N = numel(blub); % number of unique strings found
str_onsets=cell(N,1);
str_offsets=cell(N,1);
for ii=1:N
x=ic==ii;
str_onsets{ii} = strfind([0 x],[0 1]);
str_offsets{ii}= strfind([x 0],[1 0]);
end

Related

how can I change values from a nested list accordingly?

I am making a game which requires me to randomly select 2 buildings from a pool of different buildings, and after choosing 1 of the 2 buildings the count from the building pool will be deducted. I am having troubles changing the values of the selected items in the nested loop. Is there any way I can change it? This is my current code:
building_list = [['house', 8], ['hospital', 8], ['shopping-center', 8], ['airport', 8], ['park', 8]]
building_list1 = random.choice(building_list)[0]
building_list2 = random.choice(building_list)[0]
If you have concern about the performance of removing the "chosen" building, then I will propose different approach to this problem. The reason is that to constant search and remove list item is not efficient.
Please let me know if you have question.
n = 2 # select 2 buildings to pop
while n: # n is not zero: means it's True
random.shuffle(building_list)
building_pop = building_list.pop() # remove last item from list is O(1)
print(build_pop)
# do whatever you want to this two building here <----
n -= 1
this looks complex but basically we are finding what the random item was then decrementing its value by 1 then getting the name of the building.
import random
building_list = [['house', 8], ['hospital', 8], ['shopping-center', 8],
['airport', 8], ['park', 8]]
building1 = random.choice(building_list)
building_list[building_list.index(building1)][1] -= 1
building_list1 = building1[0]
print(building1)
print(building_list1)
building2 = random.choice(building_list)
building_list[building_list.index(building2)][1] -= 1
building_list2 = building2[0]
print(building2)
print(building_list2)
I got this output:
['shopping-center', 7]
shopping-center
['hospital', 7]
hospital

MiniZinc: Obtain a super set of array of sets

I am working on a constraint programming problem but stuck at a specific step and need suggestions.
My data has a bunch of orders with each order having some SKUs. I want to group these orders in different batches and then count unique SKUs in a batch/group. For e.g.
Order 1 - SKUs 1, 2, 3
Order 2 - SKUs 2, 5
Order 3 - SKUs 1, 3, 7
Order 4 - SKUs 3, 4, 6
Now, if I group Orders 1 & 4 in Batch 1 while Orders 2 & 3 in Batch 2 then following will be unique SKU count in each batch:
Batch 1 - SKUs 1, 2, 3, 4, 6 = 5 SKUs
Batch 2 - SKUs 1, 2, 3, 5, 7 = 5 SKUs
My code is as below
include "globals.mzn";
int: N_Orders = 14; % Number of orders
set of int: ORDERS = 1..N_Orders;
set of int: skuids = {1,2,3,4,5}; % Distinct sku ids across all orders
array[ORDERS] of set of skuids: oskuids = [{1,2,3},{1,3},{4},{4,5},{1},{1,4},{3,4},{5},{1,4,5},{1,2,3},{1,3},{4,5},{1},{1,4}]; % Distinct SKU ids in each order
% Orders per batch
ORDERS: x = 2;
% Batches needed
int: N_Batches = 7;
% Define array that contains batch for each order
array[ORDERS] of var 1..N_Batches: obatch;
constraint global_cardinality(obatch, [i | i in (1..N_Batches-1)], [x | i in 1..(N_Batches-1)]); % Total orders in batch set to 'x'
% Distinct skus in each batch
array[1..N_Batches] of var int: skus_in_batch;
constraint forall(i in 1..N_Batches)(
skus_in_batch[i] = card(array_union(o in ORDERS where obatch[o] = i)(oskuids[o]))
);
solve satisfy;
On running this code, I get following error:
MiniZinc: type error: no function or predicate with this signature found: `array_union(array[int] of var opt set of int)'
How can I modify code to give me the required result?
If I understand it correctly, you can simply use sum instead:
constraint forall(i in 1..N_Batches)(
skus_in_batch[i] = sum([obatch[o] = i | o in ORDERS])
);
The first solution is then
obatch = array1d(1..14 ,[7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1]);
skus_in_batch = array1d(1..7 ,[2, 2, 2, 2, 2, 2, 2]);
Here is the answer I received from the architects of MiniZinc on another forum and realized that this method can be used at many other similar situations where we receive error due to unsupported option types -
The expression
skus_in_batch[i] = card(array_union(o in ORDERS where
obatch[o] = i)(oskuids[o]));
Is effectively equivalent to
skus_in_batch[i] = card(array_union([ if obatch[o] = i then oskuids[o] else top endif | o in ORDERS]]);
and hence fails since array_union is not able to handle the array of
optional sets that are created. You can simple rewrite it to below to
avoid option types.
skus_in_batch[i] = card(array_union([ if obatch[o] = i then oskuids[o] else {} endif | o in ORDERS]]);
or equivalently
skus_in_batch[i] = card(array_union(o in ORDERS)
(if obatch[o] = i then oskuids[o] else {} endif));

Groovy: String to integer array

Im coding in Groovy and I have a string parameter "X" which looks like this:
899-921-876-123
For now i succesfully removed the "-" from it by
replaceAll("-", "")
And now I want to divide this String into separete numbers - to an array, like (8,9,9...) to make some calculations using those numbers. But somehow I cannot split() this String and make it an Integer at the same time like that:
assert X.split("")
def XInt = Integer.parseInt(X)
So then when Im trying something like:
def sum = (6* X[0]+ 5 * X[1] + 7 * X[2])
I get an error that "Cannot find matching method int#getAt(int). Please check if the declared type is right and if the method exists." or "Cannot find matching method int#multiply(java.lang.String). Please check if the declared type is right and if the method " if im not converting it to Integer...
Any idea how can I just do calculations on separate numbers of this string?
def X = '899-921-876-123'
def XInt = X.replaceAll(/\D++/, '').collect { it as int }
assert XInt == [8, 9, 9, 9, 2, 1, 8, 7, 6, 1, 2, 3]
assert 6* XInt[0]+ 5 * XInt[1] + 7 * XInt[2] == 6* 8+ 5 * 9 + 7 * 9
the replaceAll removes all non-digits
the collect iterates over the iterable and converts all elements to ints
a String is an iterable of its characters
Given you already just have a string of numbers:
"123"*.toLong() // or toShort(), toInteger(), ...
// ===> [1, 2, 3]
If found #cfrick approach the most grooviest solution.
This makes it complete:
def n = "899-921-876-123".replaceAll("-", "")
print n*.toInteger()

How to find how many items are in the same position in two lists?python

I need to be able to check if any items in one list are also in another list but in the same position. I have seen others but they return true or false. I need to know how many are in the same position.
So compare them directly!
This of course is assuming both lists are the same length:
a = [1, 1, 2, 3, 4, 5, 7, 8, 9]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9]
matches = 0
for index in range(len(a)):
if a[index] == b[index]:
matches += 1
print mat
Try it here!
overlap = set(enumerate(listA)).intersection(set(enumerate(listB))
print(len(overlap))
enumerate pairs up elements with their index, so you can check how many common element/ index pairs exist between the two lists.
One advantage of this approach (as opposed to iterating through either list yourself) is that it automatically takes care of the case where the lists have different lengths.
demo

Underscore GroupBy Sort

I have a question regarding programming in function style.
I use underscore.js library.
Let's consider some use-case. I have an array of some labels with repetitions I need to count how many occurrences of each label is in array and sort it according to the number of occurrences.
For counting, how many labels I can use countBy
_.countBy([1, 2, 3, 4, 5], function(num) {
return num % 2 == 0 ? 'even': 'odd';
});
=> {odd: 3, even: 2}
But here, as result I have a hash, which doesn't have meaning for order, so there is no sort. So here, I need to convert the hash to array then to sort it and convert backward to hash.
I am pretty sure there is an elegant way to do so, however I am not aware of it.
I would appreciate any help.
sort it and convert backward to hash.
No, that would loose the order again.
You could use
var occurences = _.countBy([1, 2, 3, 4, 5], function(num) {
return num % 2 == 0 ? 'even': 'odd';
});
// {odd: 3, even: 2}
var order = _.sortBy(_.keys(occurences), function(k){return occurences[k];})
// ["even", "odd"]
or maybe just
_.sortBy(_.pairs(occurences), 1)
// [["even", 2], ["odd", 3]]

Resources