Kusto Scan - how to deal with "optional" columns? - sequence

Can I use the SCAN operator to find sequences with values that occur only sporadically ?
Example use case: A computer raises a certain error message (B) in the boot phase (A to C). The error occurs only sporadically.
let Events = datatable (ts: datetime, Event: string) [
datetime("2022-12-01"), "A", //Start
datetime("2022-12-02"), "B", //An Error - occurs only sometimes
datetime("2022-12-03"), "C" //End
]
;
Events
| sort by ts asc
| scan with
(
step s1: Event == "A";
step s2: Event == "B";
step s3: Event == "C";
)
With this code, scan would find C only if B exsists.
But I am searching for all sequences A to C, no matter if B occurs or not.

let Events = datatable (ts: datetime, Event: string) [
datetime("2022-12-01"), "A", //Start
datetime("2022-12-02"), "B", //An Error - occurs only sometimes
datetime("2022-12-03"), "C" //End
]
;
Events
| sort by ts asc
| scan with
(
step s1 : Event == "A";
step s2 : Event in ("B", "C") and s2.Event != "C";
)
ts
Event
2022-12-01T00:00:00Z
A
2022-12-02T00:00:00Z
B
2022-12-03T00:00:00Z
C
Fiddle

Related

Compose maps using key and value in Kotlin

I have two maps and I want to merge using some rules
val a = mapOf(1 to 101, 2 to 102, 3 to 103)
val b = mapOf(101 to "a", 102 to "b", 103 to "c")
is there a way to merge using values for a and key for b
val result = mapOf(1 to "A", 2 to "b", 3 to "c")
Since the values of a and the keys of b will always match, you can do this with a single mapValues
val result = a.mapValues { (_, v) -> b.getValue(v) }
getValue can be safely used here since the key v always exist in b as a consequence of our assumption.
In general, if b may not have all the values of a as keys, you can do:
val result = a.entries.mapNotNull { (k, v) -> b[v]?.let { k to it } }.toMap()
This removes the key from the result, if the key's corresponding value in a doesn't exist as a key in b. You can also use this as an alternative if you don't like the !! in the first solution.
mapNotNull and toMap loops through the entries one time each. If that is a problem for you, use asSequence:
a.asSequence().mapNotNull { (k, v) -> b[v]?.let { k to it } }.toMap()
Since you're sure each value from map a is present in map b, this should be as simple as using mapValues and using the value of that key in map b
a.mapValues { entry ->
b[entry.value]
}
Due to having to edit and redo my answer, #Sweeper beat me to it and provided a more in-depth answer.

Find all numbers adding up to given number and range to use

This is not homework, but a real world application I'm getting stumped on.
The best way I can explain my problem is as follows:
Imagine you have 3 pig pens A, B, and C and 10 pigs to be kept.
The pens have restrictions in that each pen must contain at least 1 pig and A.pigs <= B.pigs <= C.pigs. List all the possible pen configurations.
The REAL application can have anywhere between 1 and 7 pens, and anywhere between numPens and numPens*30 pigs and no pen may contain more than 30 pigs. So essentially this translates into "what numbers between 1 and 30 (repeats allowed) add up to X using Y numbers"
This could be solved simply with nested loops, but thats a terrible inefficient solution especially knowing the scope of the real application:
var cnt = 0
val target = 10
for (a in 1..30) {
for (b in a..30) {
val c = target - a - b
cnt++
if (a <= b && b <= c && a + b + c == target) {
println("$a $b $c")
}
}
}
println(cnt)
output:
1 1 8
1 2 7
1 3 6
1 4 5
2 2 6
2 3 5
2 4 4
3 3 4
465
I'm sure there is a recursive solution to this problem. But I'm having trouble even finding the starting point for this one.
It seems easy to start with an array of [1, 1, 8] where each index represents a pen. Just put all the pigs in 1 pen and move them around 1 at a time while following the constraints.
Subtract from C, add to B as much as you can while keeping constraints gets us [1, 2, 7], [1, 3, 6], [1, 4, 5] but at that point I'm stuck code wise.
What I have currently:
fun main(vararg args: String) {
val list = arrayOf(1, 1, 8)
list.forEach { print("$it\t") }
println()
rec(list, list.lastIndex - 1)
}
fun rec(list: Array<Int>, index: Int) {
if (index == list.lastIndex || index < 0) {
return
}
while (list[index] + 1 <= list[index + 1] - 1) {
list[index]++
list[index + 1]--
list.forEach { print("$it\t") }
println()
}
}
Obviously I need to call rec somewhere within itself and probably need some conditionals to call rec correctly (possibly adding more parameters to it). The question is where and how? Normally not bad with recursion, but this one is stumping me.
Solution:
I got so hung up on the idea I needed recursion. This loop seems to work pretty well.
for (a in 1..30) {
// we know a and c must be at least b, so cap range
var b = a
while(b < min(target - a - b, 30)){
val c = target - a - b
cnt++
if (a <= b && b <= c && a + b + c == target) {
println("$a $b $c")
}
b++
}
}
Some inefficiencies to note:
Once you know a and b, the only value for c that could make a solution would be 10-a-b, so you don't need the innermost loop at all.
Since a<=b, the second loop should start at a, not 1.
You can also limit the top of the second loop's range based on the value of a

Do something every nth iteration of loop in Objective-c or Swift

Within a loop, it is possible to do something every other time by using odd and even and testing for even. I would like to do something a fixed number of times eg four no matter how many iterations there are in the loop (value of i). Is there a way to do something every nth time?
I think there must be a way by incrementing a second counter, but having trouble getting it.
A Loop
int i = 0;
int movinglimit = 0;
int incr = [myItems count]/4;;// there might be 10, 20 or 30 items. I only want to do something four times
while (i < [myItems count]) {
if ((i % 2) == 0) {
//do something if even
}
if (i>movinglimit) {
//do something a total of four times
}
if (i==moving limit+1) {
movinglimit = movinglimit + incr;
}
i++;
}
Assuming myItems is an NSArray or NSMutableArray or NSSet you can apply methods on all objects at once which is smarter than implementing an iteration looping thru object by object yourself. That way you take full advantage of objC.
[myItems makeObjectsPerformSelector:#selector(yourObjectMethodToApply)];
This has the side effect that nothing is done/applied if myItems is nil
A short comment on your pseudocode.
Be careful with while loops without any increment inside.
The one you show here is only looping once.
//iteration backward
NSUInteger i = myItems.count-1;
for ( ; i>0; ) {
if ((i % 2) == 0) {
// do stuff if 4th is even
}
// do stuff on every 4th one
i-=4; //increment does not have to be in for () declaration
}
identify the similarity (also backward iteration) to
NSUInteger i = myItems.count-1;
while (i>0) {
// do stuff on each 4th item
//check for odd/even
myItems[i] = i % 2 ? /* even stuff */ : /* odd stuff */;
i-=4; //decrement i
}
You tagged Swift so I assume you want Ob-C or Swift answers. You can enumerate the loop and use that enumeration (which I call n below). The first enumeration will always be 0, of course, so to simplify the even/odd parity, just add 1 to make the first iteration 1.
let data = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]
for (n, i) in data.enumerated() {
if (n+1).isMultiple(of: 2) {
print(n+1, i) // every even iteration
}
}
// output: 2 b, 4 d, 6 f, 8 h, 10 j
for (n, i) in data.enumerated() {
if (n+1) <= (4*2), (n+1).isMultiple(of: 2) {
print(n+1, i) // every even iteration but only 4 times
}
}
// output: 2 b, 4 d, 6 f, 8 h

Why does `variable++` increment the variable but `variable + 1` does not?

Here's the problem in which I encountered this issue:
The function should compare the value at each index position and score a point if the value for that position is higher. No point if they are the same. Given a = [1, 1, 1] b = [1, 0, 0] output should be [2, 0]
fun compareArrays(a: Array<Int>, b: Array<Int>): Array<Int> {
var aRetVal:Int = 0
var bRetVal:Int = 0
for(i in 0..2){
when {
a[i] > b[i] -> aRetVal + 1 // This does not add 1 to the variable
b[i] > a[i] -> bRetVal++ // This does...
}
}
return arrayOf(aRetVal, bRetVal)
}
The IDE even says that aRetVal is unmodified and should be declared as a val
What others said is true, but in Kotlin there's more. ++ is just syntactic sugar and under the hood it will call inc() on that variable. The same applies to --, which causes dec() to be invoked (see documentation). In other words a++ is equivalent to a.inc() (for Int or other primitive types that gets optimised by the compiler and increment happens without any method call) followed by a reassignment of a to the incremented value.
As a bonus, consider the following code:
fun main() {
var i = 0
val x = when {
i < 5 -> i++
else -> -1
}
println(x) // prints 0
println(i) // prints 1
val y = when {
i < 5 -> ++i
else -> -1
}
println(y) // prints 2
println(i) // prints 2
}
The explanation for that comes from the documentation I linked above:
The compiler performs the following steps for resolution of an operator in the postfix form, e.g. a++:
Store the initial value of a to a temporary storage a0;
Assign the result of a.inc() to a;
Return a0 as a result of the expression.
...
For the prefix forms ++a and --a resolution works the same way, and the effect is:
Assign the result of a.inc() to a;
Return the new value of a as a result of the expression.
Because
variable++ is shortcut for variable = variable + 1 (i.e. with assignment)
and
variable + 1 is "shortcut" for variable + 1 (i.e. without assignment, and actually not a shortcut at all).
That is because what notation a++ does is actually a=a+1, not just a+1. As you can see, a+1 will return a value that is bigger by one than a, but not overwrite a itself.
Hope this helps. Cheers!
The equivalent to a++ is a = a + 1, you have to do a reassignment which the inc operator does as well.
This is not related to Kotlin but a thing you'll find in pretty much any other language

Erlang Dynamic Record Editing

I'm storing some data in mnesia, and I'd like to be able to change most of the values involved.
The naive
change(RecordId, Slot, NewValue) ->
[Rec] = do(qlc:q([X || X <- mnesia:table(rec), X#rec.id =:= RecordId])),
NewRec = Rec#rec{Slot=NewValue},
F = fun() -> mnesia:write(NewRec) end,
{atomic, Val} = mnesia:transaction(F),
Val.
doesn't do it; the compiler complains that Slot is not an atom or _. Is there a way to express a general slot editing function as above, or am I going to be stuck defining a whole bunch of change_slots?
A marginally better approach is to pull out the insert and find pieces
atomic_insert(Rec) ->
F = fun() -> mnesia:write(Rec) end,
{atomic, Val} = mnesia:transaction(F),
Val.
find(RecordId) ->
[Rec] = do(qlc:q([X || X <- mnesia:table(rec), X#rec.id =:= RecordId])),
Rec.
change(RecordId, name, NewValue) ->
Rec = find(RecordId),
NewRec = Rec#rec{name=NewValue},
atomic_insert(NewRec);
change(RecordId, some_other_property, NewValue) ->
Rec = find(RecordId),
NewRec = Rec#rec{some_other_property=NewValue},
...
but there's still a bit of code duplication there. Is there any way to abstract that pattern out? Is there an established technique to allow records to be edited? Any ideas in general?
Since records are represented by tuples, you could try using tuple operations to set individual values.
-module(rec).
-export([field_num/1, make_rec/0, set_field/3]).
-record(rec, {slot1, slot2, slot3}).
make_rec() ->
#rec{slot1=1, slot2=2, slot3=3}.
field_num(Field) ->
Fields = record_info(fields, rec),
DifField = fun (FieldName) -> Field /= FieldName end,
case length(lists:takewhile(DifField, Fields)) of
Length when Length =:= length(Fields) ->
{error, not_found};
Length ->
Length + 2
end.
set_field(Field, Value, Record) ->
setelement(field_num(Field), Record, Value).
set_field will return an updated record:
Eshell V5.9.1 (abort with ^G)
1> c(rec).
{ok,rec}
2> A = rec:make_rec().
{rec,1,2,3}
3> B = rec:set_field(slot3, other_value, A).
{rec,1,2,other_value}
You can also define change as a macro (especially if it used only inside the module):
-define(change(RecordId, Slot, NewValue),
begin
[Rec] = do(qlc:q([X || X <- mnesia:table(rec), X#rec.id =:= RecordId])),
NewRec = Rec#rec{Slot=NewValue},
F = fun() -> mnesia:write(NewRec) end,
{atomic, Val} = mnesia:transaction(F),
Val
end).
Usage:
test(R, Id) ->
?change(Id, name, 5).
With macro you can also pass _ as a field (good for pattern matching).
Another way of using that a record is really a tuple would be:
change(RecordId, Index, NewValue) ->
[Rec] = do(qlc:q([X || X <- mnesia:table(rec), X#rec.id =:= RecordId])),
NewRec = setelement(Index, Rec, NewValue),
F = fun() -> mnesia:write(NewRec) end,
{atomic, Val} = mnesia:transaction(F),
Val.
which you could use like this:
5> Val = record:change(id58, #rec.name, new_value).
This is also a "clean" use of records as tuples as you are using the #rec.name syntax to find the index of the field in the tuple. It was the reason this syntax was added.