Comparison operator giving wrong answer in python - mergesort

This is the file
12,221,311,4,5,6,71,22
Output
('L:', ['12', '221', '311', '4'])
('R:', ['5', '6', '71', '22'])
('L,R', '12', '5')
false
******This condition is giving wrong result (if 12<5) its still going in this loop
Code:
def merge(Array,start,end,mid):
A=Array
p=start
q=end
r=mid
size1=q-p+1
size2=r-q
print("size1:", size1)
print("size2:", size2)
L=[None]*size1
R=[None]*size2
#print("L[]", L)
for i in range(size1):
print("i:", i)
L[i]=A[p+i]
print("L:", L)
for j in range(size2):
R[j]=A[q+j+1]
print("R:", R)
#L[size1+1]=99999
#R[size2+1]=99999
i,j=0,0
B=[None]*(r+1)
print("L,R", L[0],R[0])
**#Getting a error here...the condition down is giving wrong answer...**
if L[0]<R[0]:
print("false")
for k in range(p,r+1,1):
print("i:",i)
print("j:",j)
if L[i]<=R[j]:
B[k]=L[i]
i=i+1
else:
B[k]=R[j]
j=j+1
print(B)
def merge_sort(Array,start,end):
p=start
r=end
A=Array
if p<r:
print("P:",p)
print("R:",r)
q=(p+r)/2
print("Q:",q)
#merge_sort(A,p,q)
#merge_sort(A,q+1,r)
merge(A,p,q,r)
def main():
p=0
f = open('input.txt', 'r')
A=[]
#B=[]
for ch in f:
A=ch.split(',')
f.close()
print("Unsorted list")
print(A)
r=len(A)
merge_sort(A,p,r-1)
if __name__=="__main__":
main()

It's because you are comparing strings.
Change the main function to this:
def main():
p=0
f = open('input.txt', 'r')
A=[]
#B=[]
for ch in f:
A=ch.split(',')
f.close()
A = [int(x) for x in A] #<--- Convert values to ints
print("Unsorted list")
print(A)
r=len(A)
merge_sort(A,p,r-1)
New output:
Unsorted list
[12, 221, 311, 4, 5, 6, 71, 22]
('P:', 0)
('R:', 7)
('Q:', 3)
('size1:', 4)
('size2:', 4)
('i:', 0)
('i:', 1)
('i:', 2)
('i:', 3)
('L:', [12, 221, 311, 4])
('R:', [5, 6, 71, 22])
('L,R', 12, 5)
('i:', 0)
('j:', 0)
('i:', 0)
('j:', 1)
('i:', 0)
('j:', 2)
('i:', 1)
('j:', 2)
('i:', 1)
('j:', 3)
('i:', 1)
('j:', 4)
(And then it fails)
Traceback (most recent call last):
File "test.py", line 68, in <module>
main()
File "test.py", line 65, in main
merge_sort(A,p,r-1)
File "test.py", line 51, in merge_sort
merge(A,p,q,r)
File "test.py", line 31, in merge
if L[i]<=R[j]:
IndexError: list index out of range

Related

Create groups of sequences whose element-wise difference is 1 in Scala?

We have the following sequence of numbers: [19, 23, 24, 31, 126, 127, 155, 159, 160, 161]. We need to group this sequence according to difference between the neighboring values such that difference of values in each group would be equal to 1 if group size is > 1.
In Python, I would write something like:
outliers = [19, 23, 24, 31, 126, 127, 155, 159, 160, 161]
chains = [[i for i in list(map(itemgetter(1), g))]
for _, g in itertools.groupby(enumerate(outliers),
lambda x: x[0]-x[1])]
# [[19], [23, 24], [31], [126, 127], [155], [159, 160, 161]]
Pretty neat. But how can this be done in Scala without falling back to loops with conditions? I have been trying to do something with zipWithIndex and groupBy methods by so far to no avail :(
You can fold over the sequence, building the result as you go.
outliers.foldRight(List.empty[List[Int]]) {case (n, acc) =>
if (acc.isEmpty) List(List(n))
else if (acc(0)(0) == n+1) (n :: acc.head) :: acc.tail
else List(n) :: acc
}
//res0: List[List[Int]] = List(List(19), List(23, 24), List(31), List(126, 127), List(155), List(159, 160, 161))
Not sure if recursion can match with your conditions but it at last O(n).
def rec(source: List[Int], temp: List[Int], acc: List[List[Int]]): List[List[Int]] = source match {
case Nil => acc
case x :: xs => {
if (xs.nonEmpty && xs.head - x == 1) rec(xs, temp :+ x, acc)
else rec(xs, List(), acc :+ (temp :+ x))
}
}
val outliers = List(19, 23, 24, 31, 126, 127, 155, 159, 160, 161)
rec(outliers, List[Int](), List[List[Int]]())

Drop every Nth element from a Scala Array

My requirement is to drop every Nth element from a Scala Array (pls note every Nth element). I wrote the below method which does the job. Since, I am new to Scala, I couldn't avoid the Java hangover. Is there a simpler or more efficient alternative?
def DropNthItem(a: Array[String], n: Int): Array[String] = {
val in = a.indices.filter(_ % n != 0)
val ab: ArrayBuffer[String] = ArrayBuffer()
for ( i <- in)
ab += a(i-1)
return ab.toArray
}
You made a good start. Consider this simplification.
def DropNthItem(a: Array[String], n: Int): Array[String] =
a.indices.filter(x => (x+1) % n != 0).map(a).toArray
How about something like this?
arr.grouped(n).flatMap(_.take(n-1)).toArray
You can do this in two steps functionally using zipWithIndex to get an array of elements tupled with their indices, and then collect to build a new array consisting of only elements that have indices that aren't 0 = i % n.
def dropNth[A: reflect.ClassTag](arr: Array[A], n: Int): Array[A] =
arr.zipWithIndex.collect { case (a, i) if (i + 1) % n != 0 => a }
This will make it
def DropNthItem(a: Array[String], n: Int): Array[String] =
a.zipWithIndex.filter(_._2 % n != 0).map(_._1)
If you're looking for performance (since you're using an ArrayBuffer), you might as well track the index with a var, manually increment it, and check it with an if to filter out n-multiple-indexed values.
def dropNth[A: reflect.ClassTag](arr: Array[A], n: Int): Array[A] = {
val buf = new scala.collection.mutable.ArrayBuffer[A]
var i = 0
for(a <- arr) {
if((i + 1) % n != 0) buf += a
i += 1
}
buf.toArray
}
It's faster still if we traverse the original array as an iterator using a while loop.
def dropNth[A: reflect.ClassTag](arr: Array[A], n: Int): Array[A] = {
val buf = new scala.collection.mutable.ArrayBuffer[A]
val it = arr.iterator
var i = 0
while(it.hasNext) {
val a = it.next
if((i + 1) % n != 0) buf += a
i += 1
}
buf.toArray
}
I'd go with something like this;
def dropEvery[A](arr: Seq[A], n: Int) = arr.foldLeft((Seq.empty[A], 0)) {
case ((acc, idx), _) if idx == n - 1 => (acc, 0)
case ((acc, idx), el) => (acc :+ el, idx + 1)
}._1
// example: dropEvery(1 to 100, 3)
// res0: Seq[Int] = List(1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26, 28, 29, 31, 32, 34, 35, 37, 38, 40, 41, 43, 44, 46, 47, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80, 82, 83, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 100)
This is efficient since it requires a single pass over the array and removes every nth element from it – I believe that is easy to see.
The first case matches when idx == n - 1 and ignores the element at that index, and passes over the acc and resets the count to 0 for the next element.
If the first case doesn't match, it adds the element to the end of the acc and increments the count by 1.
Since you're willing to get rid of the Java hangover, you might want to use implicit classes to use this in a very nice way:
implicit class MoreFuncs[A](arr: Seq[A]) {
def dropEvery(n: Int) = arr.foldLeft((Seq.empty[A], 0)) {
case ((acc, idx), _) if idx == n - 1 => (acc, 0)
case ((acc, idx), el) => (acc :+ el, idx + 1)
}._1
}
// example: (1 to 100 dropEvery 1) == Nil (: true)

How to remove negative numbers from a Seq except the first negative number?

How to remove all negative numbers from a sequence, except the first negative number. I'm not to sure how to keep the first negative number and then remove the other negative numbers.
def negativeNumbers(sequence: Iterable[Int]): Iterable[Int] = {
sequence.filter(_ > 0)
return sequence
}
negativeNumbers(Seq(6, 2, -4, 7, 9, 10, -15, 8, -20))
after execution I should get Seq(6 , 2 , -4 , 7 , 9 , 10 , 8)
Because -4 is the FIRST negative number which means it doesn't get remove, But the other negative numbers get removed.
span gets you close:
scala> val vs = Seq(6, 2, -4, 7, 9, 10, -15, 8, -20)
vs: Seq[Int] = List(6, 2, -4, 7, 9, 10, -15, 8, -20)
scala> val (pos, rest) = vs span (_ >= 0)
pos: Seq[Int] = List(6, 2)
rest: Seq[Int] = List(-4, 7, 9, 10, -15, 8, -20)
scala> (pos :+ rest.head) ++ (rest.tail filter (_ >= 0))
res0: Seq[Int] = List(6, 2, -4, 7, 9, 10, 8)
Edit:
scala> def f(vs: Iterable[Int]) = {
| val (pos, rest) = vs span (_ >= 0)
| (pos ++ rest.headOption) ++ (rest drop 1 filter (_ >= 0))
| }
f: (vs: Iterable[Int])Iterable[Int]
scala> f(List(1,2,3))
res9: Iterable[Int] = List(1, 2, 3)
scala> f(vs)
res10: Iterable[Int] = List(6, 2, -4, 7, 9, 10, 8)
You can do
seq.foldLeft(false -> List.empty[Int]) {
case ((true, ls), neg) if (neg < 0) =>
true -> ls // after firstFound=true
case ((false, ls), neg) if (num < 0) =>
true -> (ls :+ neg)
case ((firstFound, ls), positive) =>
first -> (ls :+ positive)
}._2 // get just List from last state
Split the list into the leading bit with non-negative elements and the rest (which, if non-empty, must start with a negative number). Remove the other negative numbers from the rest
def negativeNumbers(sequence: Iterable[Int]): Iterable[Int] = {
val (before, after) = sequence.span(_>=0)
if (after.isEmpty) before else before ++ Iterable(after.head) ++ after.tail.filter(_>=0)
}
val seq = Seq(6, 2, -4, 7, 9, 10, -15, 8, -20)
val neg = seq.filter{a => a<0}
seq.filter{ b => b>0 || b == neg.headOption.getOrElse(-1)}
My way to do it would be to use scanLeft to track whether the first negative number has been found and then collect the results:
val s = Seq(6, 2, -4, 7, 9, 10, -15, 8, -20)
s.zip(s.scanLeft(true){
(b,i) => b && i >= 0
}).collect{
case (i,b) if b || i >= 0 => i
}

Get list of primes to N

I'm trying to write a function which takes an Int and returns all of the prime numbers up to and including that Int.
for example "list of primes for 8" = List(3,5,7)
This is what I have so far :
def isPrime(i: Int): Boolean = {
if (i <= 1)
false
else if (i == 2)
true
else
!(2 to (i - 1)).exists(x => i % x == 0)
} //> isPrime: (i: Int)Boolean
def getListOfPrimesToN(n : Int) = {
}
for the function getListOfPrimesToN I plan to
1. create a List "l" of size n and populate it with elements ranging from 0 to n.
2. call map function of "l" and call isPrime for each element in List.
How to create the List of element 1 to N ?
Any alternative solutions for returning all of the prime numbers up to and including an Int N welcome.
You can solve this with infinite streams. If you had a stream primes of all the primes, you could just say primes.takeWhile(_ <= n) to get the primes up to and including n.
To get all the primes, you start with a stream of all the numbers starting from 2, the first prime. You can then skip all the even numbers since those are definitely not prime. Then you can skip all the other numbers that are not prime.
val primes = 2 #:: Stream.from(3,2).filter(isPrime)
Now you just need isPrime to check if a given number is prime. A number is prime if it is not divisible by any smaller prime. We actually need only consider primes whose square is not greater than the number (since, logically, a composite number's smallest prime factor can't be larger than its square root).
def isPrime(n: Int): Boolean =
primes.takeWhile(p => p*p <= n).forall(n % _ != 0)
Check this in the REPL:
scala> primes.takeWhile(_ <= 8).toList
res0: List[Int] = List(2, 3, 5, 7)
Caveat: This only works for positive numbers smaller than Integer.MAX_VALUE.
An implementation of the Sieve of Eratosthenes algorithm for efficiently finding prime numbers up to a given value N includes the following, (fixed and improved on this SO answer),
implicit class Sieve(val N: Int) extends AnyVal {
def primesUpTo() = {
val isPrime = collection.mutable.BitSet(2 to N: _*) -- (4 to N by 2)
for (p <- 2 +: (3 to Math.sqrt(N).toInt by 2) if isPrime(p)) {
isPrime --= p*p to N by p
}
isPrime.toImmutable
}
}
Hence
10.primesUpTo.toList
res: List(2, 3, 5, 7)
11.primesUpTo.toList
res: List(2, 3, 5, 7, 11)
Note Find prime numbers using Scala. Help me to improve for additional ideas and discussion.
Here is the code based on your:
scala> def isPrime(n: Int): Boolean =
| n >= 2 && (2 to math.sqrt(n).toInt).forall(n%_ != 0)
isPrime: (n: Int)Boolean
scala> def getListOfPrimesToN(n: Int): List[Int] =
| List.range(2, n+1) filter isPrime
getListOfPrimesTON: (n: Int)List[Int]
scala> getListOfPrimesToN(97)
res0: List[Int] = List(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97)
Here is another solution using Stream:
scala> def getListOfPrimesToN(n: Int): List[Int] = {
| lazy val ps: Stream[Int] = 2 #:: Stream.from(3)
.filter(x => ps.takeWhile(p => p*p <= x).forall(x%_ != 0))
| ps.takeWhile(_ <= n).toList
| }
getListOfPrimesToN: (n: Int)List[Int]
scala> getListOfPrimesToN(97)
res0: List[Int] = List(2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97)
How about this.
def getPrimeUnder(n: Int) = {
require(n >= 2)
val ol = 3 to n by 2 toList // oddList
def pn(ol: List[Int], pl: List[Int]): List[Int] = ol match {
case Nil => pl
case _ if pl.exists(ol.head % _ == 0) => pn(ol.tail, pl)
case _ => pn(ol.tail, ol.head :: pl)
}
pn(ol, List(2)).reverse
}

How to sum up based on a Tuples first elem?

I have a 3-tuple list like the following [I added line breaks for readability]:
(2, 127, 3)
(12156, 127, 3)
(4409, 127, 2) <-- 4409 occurs 2x
(1312, 127, 12) <-- 1312 occurs 3x
(4409, 128, 1) <--
(12864, 128, 1)
(1312, 128, 1) <--
(2664, 128, 2)
(12865, 129, 1)
(183, 129, 1)
(12866, 129, 2)
(1312, 129, 10) <--
I want to sum up based on the first entry. The first entry should be unique.
The result should look like this:
(2, 127, 3)
(12156, 127, 3)
(4409, 127, 3) <- new sum = 3
(1312, 127, 23) <- new sum = 23
(12864, 128, 1)
(2664, 128, 2)
(12865, 129, 1)
(183, 129, 1)
(12866, 129, 2)
How can I achieve this in Scala?
Try this:
list groupBy {_._1} mapValues {v => (v.head._1, v.head._2, v map {_._3} sum)}
The middle entry is preserved and it always takes the first one that appeared in the input list.
If you can just ignore the middle entry, then:
val l = List(('a,'e,1), ('b,'f,2), ('a,'g,3), ('b,'h,4))
l.groupBy(_._1).mapValues(_.map(_._3).sum)
// Map('b -> 6, 'a -> 4)
If you have to keep the middle entry around:
l.groupBy(_._1).map {
case (_, values) =>
val (a,b,_) = values.head
(a, b, values.map(_._3).sum)
}
// List(('b,'f,6), ('a,'e,4))
You could use the concept of a monoid. If the first two values of your entries build the key values and the remaining the associate value itself, you could use a Map.
Once you have a Map you may proceed like this:
Best way to merge two maps and sum the values of same key?