Related
In Raku, how does one write the equivalent of Haskell's span function?
In Haskell, given a predicate and a list, one can split the list into two parts:
the longest prefix of elements satisfying the predicate
the remainder of the list
For example, the Haskell expression …
span (< 10) [2, 2, 2, 5, 5, 7, 13, 9, 6, 2, 20, 4]
… evaluates to …
([2,2,2,5,5,7],[13,9,6,2,20,4])
How does one write the Raku equivalent of Haskell's span function?
Update 1
Based on the answer of #chenyf, I developed the following span subroutine (additional later update reflects negated predicate within span required to remain faithful to the positive logic of Haskell's span function) …
sub span( &predicate, #numberList )
{
my &negatedPredicate = { ! &predicate($^x) } ;
my $idx = #numberList.first(&negatedPredicate):k ;
my #lst is Array[List] = #numberList[0..$idx-1], #numberList[$idx..*] ;
#lst ;
} # end sub span
sub MAIN()
{
my &myPredicate = { $_ <= 10 } ;
my #myNumberList is Array[Int] = [2, 2, 2, 5, 5, 7, 13, 9, 6, 2, 20, 4] ;
my #result is Array[List] = span( &myPredicate, #myNumberList ) ;
say '#result is ...' ;
say #result ;
say '#result[0] is ...' ;
say #result[0] ;
say #result[0].WHAT ;
say '#result[1] is ...' ;
say #result[1] ;
say #result[1].WHAT ;
} # end sub MAIN
Program output is …
#result is ...
[(2 2 2 5 5 7) (13 9 6 2 20 4)]
#result[0] is ...
(2 2 2 5 5 7)
(List)
#result[1] is ...
(13 9 6 2 20 4)
(List)
Update 2
Utilizing information posted to StackOverflow concerning Raku's Nil, the following updated draft of subroutine span is …
sub span( &predicate, #numberList )
{
my &negatedPredicate = { ! &predicate($^x) } ;
my $idx = #numberList.first( &negatedPredicate ):k ;
if Nil ~~ any($idx) { $idx = #numberList.elems ; }
my List $returnList = (#numberList[0..$idx-1], #numberList[$idx..*]) ;
$returnList ;
} # end sub span
sub MAIN()
{
say span( { $_ == 0 }, [2, 2, 5, 7, 4, 0] ) ; # (() (2 2 5 7 4 0))
say span( { $_ < 6 }, (2, 2, 5, 7, 4, 0) ) ; # ((2 2 5) (7 4 0))
say span( { $_ != 9 }, [2, 2, 5, 7, 4, 0] ) ; # ((2 2 5 7 4 0) ())
} # end sub MAIN
I use first method and :k adverb, like this:
my #num = [2, 2, 2, 5, 5, 7, 13, 9, 6, 2, 20, 4];
my $idx = #num.first(* > 10):k;
#num[0..$idx-1], #num[$idx..*];
A completely naive take on this:
sub split_on(#arr, &pred) {
my #arr1;
my #arr2 = #arr;
loop {
if not &pred(#arr2.first) {
last;
}
push #arr1: #arr2.shift
}
(#arr1, #arr2);
}
Create a new #arr1 and copy the array into #arr2. Loop, and if the predicate is not met for the first element in the array, it's the last time through. Otherwise, shift the first element off from #arr2 and push it onto #arr1.
When testing this:
my #a = [2, 2, 2, 5, 5, 7, 13, 9, 6, 2, 20, 4];
my #b = split_on #a, -> $x { $x < 10 };
say #b;
The output is:
[[2 2 2 5 5 7] [13 9 6 2 20 4]]
Only problem here is... what if the predicate isn't met? Well, let's check if the list is empty or the predicate isn't met to terminate the loop.
sub split_on(#arr, &pred) {
my #arr1;
my #arr2 = #arr;
loop {
if !#arr2 || not &pred(#arr2.first) {
last;
}
push #arr1: #arr2.shift;
}
(#arr1, #arr2);
}
So I figured I'd throw my version in because I thought that classify could be helpful :
sub span( &predicate, #list ) {
#list
.classify({
state $f = True;
$f &&= &predicate($_);
$f.Int;
}){1,0}
.map( {$_ // []} )
}
The map at the end is to handle the situation where either the predicate is never or always true.
In his presentation 105 C++ Algorithms in 1 line* of Raku (*each) Daniel Sockwell discusses a function that almost answers your question. I've refactored it a bit to fit your question, but the changes are minor.
#| Return the index at which the list splits given a predicate.
sub partition-point(&p, #xs) {
my \zt = #xs.&{ $_ Z .skip };
my \mm = zt.map({ &p(.[0]) and !&p(.[1]) });
my \nn = mm <<&&>> #xs.keys;
return nn.first(?*)
}
#| Given a predicate p and a list xs, returns a tuple where first element is
#| longest prefix (possibly empty) of xs of elements that satisfy p and second
#| element is the remainder of the list.
sub span(&p, #xs) {
my \idx = partition-point &p, #xs;
idx.defined ?? (#xs[0..idx], #xs[idx^..*]) !! ([], #xs)
}
my #a = 2, 2, 2, 5, 5, 7, 13, 9, 6, 2, 20, 4;
say span { $_ < 10 }, #a; #=> ((2 2 2 5 5 7) (13 9 6 2 20 4))
say span { $_ < 5 }, [6, 7, 8, 1, 2, 3]; #=> ([] [6 7 8 1 2 3])
Version 6.e of raku will sport the new 'snip' function:
use v6.e;
dd (^10).snip( * < 5 );
#«((0, 1, 2, 3, 4), (5, 6, 7, 8, 9)).Seq»
Hello I need a help with writing a regex to sort an house addresses.
I have list of adresses like: val list = listOf("1", "5b", "1b", "1c", "1-10", "5", "5a", "10"))
After sorting it : result should be :
1, 1-10, 1b, 1c, 5, 5a, 5b, 10
Edited to match your changed question:
fun sortMyThing(list: List<String>): List<String> {
val cmp = Comparator<String> { a, b ->
val intA = a.replace("(\\d+).*".toRegex(), "$1").toInt()
val intB = b.replace("(\\d+).*".toRegex(), "$1").toInt()
if (intA == intB) {
a.compareTo(b) //otherwise 1-10 goes after 1c
} else {
intA - intB
}
}
return list.sortedWith(cmp)
}
I get result: 1, 1-10, 1b, 1c, 5, 5a, 5b, 10
I want to using case on if statement, can I use it? Because I always got error when i compile it ;w;
Error I got:
Tahun.pas(26,21) Fatal: Syntax error, ";" expected but "ELSE" found
Tahun.pas(0) Fatal: Compilation aborted
Here my code:
uses Crt;
var
sisa, bulan, tahun : integer;
begin
ClrScr;
writeln('masukkan tahun'); read(tahun);
sisa := tahun mod 4;
if sisa =0 then
writeln('masukkan bulan 1-12'), read(bulan);
case bulan of
1: write('31');
2: write('29');
3: write('31');
4: write('30');
5: write('31');
6: write('30');
7: write('31');
8: write('30');
9: write('31');
10: write('30');
11: write('31');
12: write('30');
else write('bulan tidak lebih dari 12');
end;
else
writeln('masukkan bulan 1-12'), read(bulan);
case bulan of
1: write('31');
2: write('28');
3: write('31');
4: write('30');
5: write('31');
6: write('30');
7: write('31');
8: write('30');
9: write('31');
10: write('30');
11: write('31');
12: write('30');
else write('bulan tidak lebih dari 12')
end;
readln;
readln;
end.
Or maybe you know how to improve the code? ;w;
Thank you for answering ;w;
I hope you have read the links upon the pieces of advice given in the comments yesterday. So there are several possible answers to the question:
The 1st – to repair your code:
begin
writeln('masukkan tahun');
readln(tahun);
writeln('masukkan bulan 1-12');
readln(bulan);
case bulan of
1, 3, 5, 7, 8, 10, 12: writeln('31');
2: if tahun mod 4 = 0 then
writeln('29')
else
writeln('28');
4, 6, 9, 11: writeln('30');
else
write('bulan tidak lebih dari 12');
end;
readln;
end.
2nd – to optimize it:
const
DinM: array [boolean, 1 .. 12] of byte =
((31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31));
begin
writeln('masukkan tahun');
readln(tahun);
writeln('masukkan bulan 1-12');
readln(bulan);
writeln(DinM[tahun mod 4 = 0, bulan]);
readln;
end.
And 3rd:
Use predesigned functions: Delphi has a function DaysInAMonth described here.
Lazarus has it as well.
Note
Remember that all these methods (including standard functions) will give an error calculating leap years as not all years that year mod 4 = 0 are leap. For example year 1700, 1800, 1900, 2100 etc. are not leap.
Scala accessing list objects and evaluating number of cycles
I have list of objects
case class ItemDesc(a: Int, b: Int, c: Int, d: Int,e: Int, f: Int, g: Int desc: String)
val example = List(ItemDesc(6164,6165,6166,-6195,-6175,-6186,-6195, The values are correct), ItemDesc(14879,-14879,14879,-14894, 14879,14879,14894, The values are ok), ItemDesc(19682,-19690,-19682,19694,19690,19682,19694,The values are good),ItemDesc(5164,-5165,-5166,-6195,5165,5166,6195,The values are correct),ItemDesc(5879,5879,5879,5894,5879,5879,5879,The values are ok))
From the 'example' List, I want to access object 'ItemDesc'. And get the count of cycles. how many times it turns from negative to positive and stays positive for >= 2 seconds.
If >= 2 seconds it is a cycle.
Example 1: (6164,6165,6166,-6195,-6175,-6186,-6195, good)
No. of cycles is 2.
Reason: As we move from 1st element of list to 3rd element, we had 2 intervals which means 2 seconds. Interval is >= 2. So it is one cycle. As we move to 3rd element of list to 4th element, it is a negative value. So we start counting from 4th element and move to 7th element and all elements have same negative sign. we had 3 intervals which means 3 seconds. Interval is >= 2. So it is one cycle. We start counting intervals fresh from zero as one number changes from positive to negative and vice-versa.
Example 2: (14879,-14879,14879,-14894, 14879,14879,14894,better)
No. of cycles is 1.
Reason: As we move from 1st element of list to 2nd element, the sign changes to negative. So we start counting the interval from zero. From element 2 to 3, the sign changes to negative. so interval counter is zero. From element 3 to 4, the sign changes to negative. interval counter is zero. From 5th to 7th all values have same sign, we had 2 intervals which means 2 seconds. Interval is >= 2. So it is one cycle.
Example 3: (5164,-5165,-5166,-6195,5165,5166,6195,good)
No. of cycles is 2
The below code which I wrote is not giving me the no. of cycles which I am looking for. Appreciate help in fixing it.
object findCycles {
def main(args: Array[String]) {
var numberOfPositiveCycles = 0
var numberOfNegativeCycles = 0
var numberOfCycles = 0
case class itemDesc(a: Int, b: Int, c: Int, d: Int, reason: String)
val example = List(ItemDesc(6164,6165,6166,-6195,-6175,-6186,-6195, The values are correct), ItemDesc(14879,-14879,14879,-14894, 14879,14879,14894, The values are ok), ItemDesc(19682,-19690,-19682,19694,19690,19682,19694,The values are good),ItemDesc(5164,-5165,-5166,-6195,5165,5166,6195,The values are correct),ItemDesc(5879,5879,5879,5894,5879,5879,5879,The values are ok))
val data2 = example.map(x => getInteger(x)).filter(_ != "unknown").map(_.toString.toInt)
//println(data2)
var nCycle = findNCycle(data2)
println(nCycle)
}
def getInteger(obj: Any) = obj match {
case n: Int => obj
case _ => "unknown"
}
def findNCycle(obj: List[Int]) : Int = {
def NegativeCycles(fit: itemDesc): Int = {
if (fit.a < 0 && fit.b < 0 && fit.c < 0) || if( fit.b < 0 && fit.c < 0 && fit.d < 0)
{
numberOfNegativeCycles += 1
}
}
//println("negative cycle="+cycles)
def PositiveCycles(fit: itemDesc): Int = {
if (fit.a > 0 && fit.b > 0 && fit.c > 0) || if( fit.b > 0 && fit.c > 0 && fit.d > 0)
{
numberOfPositiveCycles += 1
}
}
//println("positive cycle="+cycles)
numberOfCycles = numberOfPositiveCycles + numberOfNegativeCycles
return numberOfCycles
}
}
For reference on the logic you can refer to- Number of Cycles from list of values, which are mix of positives and negatives in Spark and Scala
Ok this is rough but I think it does what you want. I'm sure there is a more elegant way to do the split method.
I haven't used your ItemDesc as its simpler to demonstrate the problem given the examples you gave.
object CountCycles extends App {
// No. of cycles is 1.
val example1 = List(1, 2, 3, 4, 5, 6, -15, -66)
// No. of cycles is 3.
val example2 = List(11, 22, 33, -25, -36, -43, 20, 25, 28)
// No. of cycles is 8
val example3 = List(1, 4, 82, 5, 6, -2, -12, -22, -32, 100, 102, 100, 102, 0, 0, -2, -12, -22, -32, 4, 82, 5, 6, -6, 8, -6, -6, 8, 8, -5, -6, -7, 9, 8, 6, -5, -6, -7)
def differentSign(x: Int, y: Int): Boolean =
(x < 0) != ( y < 0)
// return a list of sections
def split(l: List[Int]): List[List[Int]] =
l match {
case Nil ⇒ Nil
case h :: _ ⇒
val transition: Int = l.indexWhere(differentSign(h, _))
if (transition < 0) List(l)
else {
val (head, tail) = l.splitAt(transition)
head :: split(tail)
}
}
def count(l: List[Int]): Int = {
val pos: List[List[Int]] = split(l)
// count is the number of sections of length > 2
pos.count(_.length > 2)
}
println(count(example1)) // 1
println(count(example2)) // 3
println(count(example3)) // 8
}
This should be a working solution for the case where you have 7 items in the sample as shown in the description. If your case class changes and instead has a list of values then the implicit helper can be replaced with a simple call to the accessor
import scala.annotation.tailrec
import scala.language.implicitConversions
object CyclesCounter extends App {
val examples = List(
ItemDesc(6164,6165,6166,-6195,-6175,-6186,-6195, "The values are correct"),
ItemDesc(14879,-14879,14879,-14894, 14879,14879,14894, "The values are ok"),
ItemDesc(19682,-19690,-19682,19694,19690,19682,19694,"The values are good"),
ItemDesc(5164,-5165,-5166,-6195,5165,5166,6195,"The values are correct"),
ItemDesc(5879,5879,5879,5894,5879,5879,5879,"The values are ok"))
val counter = new CycleCounter
// Add the index for more readable output
examples.zipWithIndex.foreach{ case (item, index) => println(s"Item at index $index has ${counter.cycleCount(item)} cycles")}
}
class CycleCounter {
def cycleCount(item: ItemDesc): Int = {
#tailrec
def countCycles(remainingValues: List[Int], cycles: Int): Int = {
if (remainingValues.isEmpty) cycles
else {
val headItems = {
if (remainingValues.head < 0) remainingValues.takeWhile(_ < 0)
else remainingValues.takeWhile(_ >= 0)
}
val rest = remainingValues.drop(headItems.length)
if (headItems.length > 2) countCycles(rest, cycles + 1) else countCycles(rest, cycles )
}
}
countCycles(item, 0)
}
// Helper to convert ItemDesc into a List[Int] for easier processing
implicit def itemToValueList(item: ItemDesc): List[Int] = List(item.a, item.b, item.c, item.d, item.e, item.f, item.g)
}
case class ItemDesc(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int, g: Int, reason: String)
Output from running:
Item at index 0 has 2 cycles
Item at index 1 has 1 cycles
Item at index 2 has 1 cycles
Item at index 3 has 2 cycles
Item at index 4 has 1 cycles
Hope that helps
As i read, i see that your problem is to treat the case class as a single entity and no as a list of elements and a reason. I would change the case class to one of these alternatives, first one is if the amount of elements is static (4 in this case):
case class ItemDesc(a: Int, b: Int, c: Int, d: Int, reason: String) {
lazy val getAsList = List(a,b,c,d)
}
ItemDesc(1,2,3,4,"reason").getAsList
In the second case, it can be used if the amount of elements is unbounded:
case class ItemDescAlt(reason:String, elements: Int*)
ItemDescAlt("reason", 5164,-5165,-5166,-6195,5165,5166,6195)
And like the rest i will give my custom version for calculate the number of cycles:
def getCycles(list: Seq[Int]): Int = {
def headPositive(list: Seq[Int]): Boolean = {
list.headOption.forall(_ >= 0)
}
val result = list.foldLeft((0, 0, !headPositive(list))) { //we start with a symbol diferent to the firs one
case ((numberOfCycles, cycleLength, lastWasPositive), number) => { //for each element...
val numberSign = number >= 0
val actualCycleLength = if (numberSign == lastWasPositive) { //see if the actual simbol is equal to the last one
cycleLength + 1 //in that case the length is increased
} else {
0 //in the other reset it
}
val actualNCycles = if (actualCycleLength == 2) { //if the actual length is equal to to
numberOfCycles + 1 //it is a proper new cycle
} else {
numberOfCycles // no new cycles
}
(actualNCycles, actualCycleLength, numberSign) //return the actual state
}
}
result._1 //get the final number of cycles
}
If you already have a solution for List, you can convert any case class into a List using productIterator:
scala> case class X(a:Int, b:Int, c:String)
defined class X
scala> val x = X(1,2,"a")
x: X = X(1,2,a)
scala> x.productIterator.toList
res1: List[Any] = List(1, 2, a)
The main problem is that you get back a List[Any] so you might have to do more work to get a List[Int]
Suppose I have the following user/item sets where items could also be replicates for each user (like user1)
{ "u1", "item" : [ "a", "a", "c","h" ] }
{ "u2", "item" : [ "b", "a", "f" ] }
{ "u3", "item" : [ "a", "a", "f" ] }
I want to find a map-reduce algorithm that will calculate the number of common items between each pair of users some like that
{ "u1_u2", "common_items" : 1 }
{ "u1_u3", "common_items" : 2 }
{ "u2_u3", "common_items" : 2 }
It basically finds the intersections of itemsets for each pair and considers replicates as new items. I am new to mapreduce, how can I do a map-reduce for this?
With these sorts of problems, you need to appreciate that some algorithms will scale better than others, and performance of any one algorithm will depend on the 'shape' and size of your data.
Comparing the item sets for every user to every other user might be appropriate for small domain datasets (say 1000's or users, maybe even 10,000's, with a similar number of items), but is an 'n squared' problem (or an order of thereabouts, my Big O is rusty to say the least!):
Users Comparisons
----- -----------
2 1
3 3
4 6
5 10
6 15
n (n^2 - n)/2
So a user domain of 100,000 would yield 4,999,950,000 set comparisons.
Another approach to this problem, would be to inverse the relationship, so run a Map Reduce job to generate a map of items to users:
'a' : [ 'u1', 'u2', 'u3' ],
'b' : [ 'u2' ],
'c' : [ 'u1' ],
'f' : [ 'u2', 'u3' ],
'h' : [ 'u1' ],
From there you can iterate the users for each item and output user pairs (with a count of one):
'a' would produce: [ 'u1_u2' : 1, 'u1_u3' : 1, 'u2_u3' : 1 ]
'f' would produce: [ 'u2_u3' : 1 ]
Then finally produce the sum for each user pairing:
[ 'u1_u2' : 1, 'u1_u3' : 1, 'u2_u3' : 2 ]
This doesn't produce the behavior you are interested (the double a's in both u1 and u3 item sets), but details an initial implementation.
If you know your domain set typically has users which do not have items in common, a small number of items per user, or an item domain which has a large number of distinct values, then this algorithm will be more efficient (previously you were comparing every user to another, with a low probability of intersection between the two sets). I'm sure a mathematician could prove this for you, but that i am not!
This also has the same potential scaling problem as before - in that if you have an item that all 100,000 users all have in common, you still need to generate the 4 billion user pairs. This is why it is important to understand your data, before blindly applying an algorithm to it.
You want a step that emits all of the things the user has, like:
{ 'a': "u1" }
{ 'a': "u1" }
{ 'c': "u1" }
{ 'h': "u1" }
{ 'b': "u2" }
{ 'a': "u2" }
{ 'f': "u2" }
{ 'a': "u1" }
{ 'a': "u3" }
{ 'f': "u3" }
Then reduce them by key like:
{ 'a': ["u1", "u1", "u2", "u3"] }
{ 'b': ["u2"] }
{ 'c': ["u1"] }
{ 'f': ["u2", "u3"] }
{ 'h': ["u1"] }
And in that reducer emit the permutations of each user in each value, like:
{ 'u1_u2': 'a' }
{ 'u2_u3': 'a' }
{ 'u1_u3': 'a' }
{ 'u2_u3': 'f' }
Note that you'll want to make sure that in a key like k1_k2 that k1 < k2 so that they match up in any further mapreduce steps.
Then if if you need them all grouped like your example, another mapreduce phase to combine them by key and they'll end up like:
{ 'u1_u2': ['a'] }
{ 'u1_u3': ['a'] }
{ 'u2_u3': ['a', 'f'] }
{ 'u2_u3': ['f'] }
Does this work for you?
from itertools import combinations
user_sets = [
{ 'u1': [ 'a', 'a', 'c', 'h' ] },
{ 'u2': [ 'b', 'a', 'f' ] },
{ 'u3': [ 'a', 'a', 'f' ] },
]
def compare_sets(set1, set2):
sum = 0
for n, item in enumerate(set1):
if item in set2:
sum += 1
del set2[set2.index(item)]
return sum
for set in combinations(user_sets, 2):
comp1, comp2 = set[0], set[1]
print 'Common items bwteen %s and %s: %s' % (
comp1.keys()[0], comp2.keys()[0],
compare_sets(comp1.values()[0], comp2.values()[0])
)
Here's the output:
Common items bwteen u1 and u2: 1
Common items bwteen u1 and u3: 2
Common items bwteen u2 and u3: 1