Please, help me to implement subset function - arrays

I tried to copy it to array, but I can't accept two (Sets) parameters
def subset(a:Set[Int],b:Set[Int]):Boolean={
var x = new Array[Int](a.size)
var y = new Array[Int](b.size)
}
or can you explain how to recieve two arrays as parameter?
def main(args: Array[String]): Unit = {
val a = Set(2,3,4,5,6)
val b = Set(2,3,4,5)
var x = new Array[Int](a.size)
var y = new Array[Int](b.size)
i wish to put x and y to function subset and do same but not by Set

You can transform Set to Array or Array to Set:
scala> val array = Array(1, 3, 5)
array: Array[Int] = Array(1, 3, 5)
scala> array.toSet
res0: scala.collection.immutable.Set[Int] = Set(1, 3, 5)
scala> val set = Set(7, 3, 8)
set: scala.collection.immutable.Set[Int] = Set(7, 3, 8)
scala> set.toArray
res1: Array[Int] = Array(7, 3, 8)
If you want a program to take a collection of Ints as a command-line argument, you'll have to parse a string:
object Test extends App {
val x: Array[Int] = args(0).split(",").map{ _.toInt }
val y: Array[Int] = args(1).split(",").map{ _.toInt }
println("x: " + x.mkString("Array(", ", ", ")"))
println("y: " + y.mkString("Array(", ", ", ")"))
}
Usage:
>scala Test "1,2,3" "10,0,-5"
x: Array(1, 2, 3)
y: Array(10, 0, -5)

Related

How to reduce positive elements in collection in scala?

Given an integer array nums:
-2,1,-3,4,6,-1,2,1,1,-5,4
I want to transform this array to another array:
-2,1,-3,10,-1,4,-5,4
Can I add a condition to the reduce function?
Something like that:
...
val nums = Array(-2,1,-3,4,6,-1,2,1,1,-5,4)
val reduced = nums.reduce((x, y) => {
if (x > 0 && y > 0){
x + y
}
})
...
scala> val nums = Array(-2,1,-3,4,6,-1,2,1,1,-5,4)
nums: Array[Int] = Array(-2, 1, -3, 4, 6, -1, 2, 1, 1, -5, 4)
scala> nums.foldLeft(List[Int]()){
case (init :+ last, num) if last > 0 && num > 0 => init :+ (last + num)
case (res, num) => res :+ num
}
res0: List[Int] = List(-2, 1, -3, 10, -1, 4, -5, 4)
Or:
scala> def reduce(nums: Seq[Int]): Seq[Int] = nums match {
| case x1+:x2+:xs => if(x1>0 && x2>0) reduce((x1+x2)+:xs) else x1+:reduce(x2+:xs)
| case ns => ns
| }
def reduce(nums: Seq[Int]): Seq[Int]
scala> reduce(nums)
val res1: Seq[Int] = ArraySeq(-2, 1, -3, 10, -1, 4, -5, 4)
You can try next:
val result = Array(-2,1,-3,4,6,-1,2,1,1,-5,4).foldLeft(ListBuffer.empty[Int]) {
case (result, item) if item < 0 => result :+ item
case (result, item) if item > 0 => result.lastOption.filter(_ > 0).fold(result :+ item) { positiveSum =>
result.update(result.size -1, positiveSum + item)
result
}
}
println(result)
which will produce desired result: (-2, 1, -3, 10, -1, 4, -5, 4)
Hope this helps!
I am not sure if you can use reduce or another simple builtin-function to achieve your goal.
However, you can write a simple tail-recursive function that does what you want (it uses a list and pattern matching):
def sumPositives(arr: Array[Integer]): Array[Integer] = {
#scala.annotation.tailrec
def rec(list: List[Integer], acc: List[Integer]): List[Integer] = list match{
case x :: y :: rest if x >= 0 && y >= 0 => rec(x+y :: rest, acc)
case x :: y :: rest => rec(y :: rest, x :: acc)
case x :: Nil => (x :: acc).reverse
case Nil =>acc.reverse
}
rec(arr.toList, List()).toArray
}
Of course this could be simplified by using a list as input instead of an array, but in your question you specifically mentioned an array.
A simple, non-tail recursive one:
def reducePositives(l: List[Int]): List[Int] = {
l.span(_ > 0) match {
case (Nil, Nil) => Nil
case (Nil, np :: rest) => np :: reducePositives(rest)
case (p, rest) => p.sum :: reducePositives(rest)
}
}

Scala matching arrays 2d

I have 2d Array which is declared like that init_ : Array[Array[Int]]
In this 2d array, i can only have "1","2" or "3".
I'm looking to print something different when i iterate on these elements, something like that :
override def toString = {
val c = init.map(_.clone);
c match{
case 1 => ret = "one"
case 2 => ret = "two"
case 3 => ret = "three"
}
ret
}
I'm beginning in Scala so please, be indulgent
Here is my 2d arrays :
val tab = $(
$(1, 2, 3,
$(1, 2, 3,
$(1, 2, 3)
I've imported things like that : import scala.{Array => $};
Thanks
Example to iterate a two 2D array and do pattern matching
import scala.{Array => $}
val tab = $(
$(1, 2, 1),
$(1, 2, 2),
$(3, 2, 3),
$(4, 2, 4))
val rowsSize = tab.length
val columnsSize = tab(0).length
for (i <- 0 to rowsSize - 1; j <- 0 to columnsSize - 1) {
tab(i)(j) match {
case 1 => println("one")
case 2 => println("two")
case 3 => println("three")
case x => println(x)
}
}

Find all the unique pairs whose sum will be equal to a given sum

I want to find all the unique pairs whose sum will be equal to a given sum. I implement a solution but it returns only the first pair that it finds.
func checkPairs(in numbers: [Int], forSum target: Int) -> String {
for (i, x) in numbers.enumerated() {
for y in numbers[i+1 ..< numbers.count] {
if x + y == target {
return ("There is a pair that sums \(target): \(x)+\(y)=\(target)")
}
}
}
return "no pair"
}
print (checkPairs(in: [1, 2, 4, 4, 7, 5, 3], forSum: 8))
Output:
There is a pair that sums 8: 1+7=8
You exit the function early by calling return when the first pair is found. Instead, you should return an array of tuples containing the pairs, iterate over all pairs and add the ones satisfying the requirements to the return array.
func checkPairs(in numbers: [Int], forSum target: Int) -> [(Int,Int)] {
var pairs = [(Int,Int)]()
for (i, x) in numbers.enumerated() {
for y in numbers[i+1 ..< numbers.count] {
if x + y == target {
pairs.append((x,y))
}
}
}
return pairs
}
print(checkPairs(in: [1, 2, 4, 4, 7, 5, 3], forSum: 8))
Output:
[(1, 7), (4, 4), (5, 3)]
If you're looking for unique pairs, you can define a custom type holding the pair of numbers and return a Set instead of an Array (the custom type is needed, since you cannot make a Tuple conform to Hashable, which is needed to be able to add elements to a Set).
struct Pair: Hashable {
let smaller:Int
let bigger:Int
init(_ a:Int, _ b:Int) {
if a < b {
smaller = a
bigger = b
} else {
smaller = b
bigger = a
}
}
}
extension Pair: CustomStringConvertible {
var description:String {
return "\((smaller,bigger))"
}
}
func checkPairs(in numbers: [Int], forSum target: Int) -> Set<Pair> {
var pairs = Set<Pair>()
for (i, x) in numbers.enumerated() {
for y in numbers[i+1 ..< numbers.count] {
if x + y == target {
pairs.insert(Pair(x,y))
}
}
}
return pairs
}
print(checkPairs(in: [1, 2, 4, 4, 7, 5, 3], forSum: 8))
print(checkPairs(in: [1, 2, 4, 4, 7, 5, 3, 4, 1], forSum: 8))
Output:
[(4, 4), (3, 5), (1, 7)]
[(4, 4), (3, 5), (1, 7)]
here is one of options you can do
let array = [1, 2, 4, 4, 7, 5, 3]
let target = 8
func checkPairs(in numbers: [Int], forSum target: Int) -> String {
var pairs = ""
for (i, x) in numbers.enumerated() {
for y in numbers[i+1 ..< numbers.count] {
if x + y == target {
pairs += ("There is a pair that sums \(target): \(x)+\(y)=\(target)\n")
}
}
}
return pairs
}
print(checkPairs(in: array, forSum: target))
output will be There is a pair that sums 8: 1+7=8 There is a pair
that sums 8: 4+4=8 There is a pair that sums 8: 5+3=8

Repeating array in Swift

In Python I can create a repeating list like this:
>>> [1,2,3]*3
[1, 2, 3, 1, 2, 3, 1, 2, 3]
Is there a concise way to do this in Swift?
The best I can do is:
1> var r = [Int]()
r: [Int] = 0 values
2> for i in 1...3 {
3. r += [1,2,3]
4. }
5> print(r)
[1, 2, 3, 1, 2, 3, 1, 2, 3]
You can create a 2D array and then use flatMap to turn it into a 1D array:
let array = [[Int]](repeating: [1,2,3], count: 3).flatMap{$0}
If you want to have a general way of doing this, here's an extension that adds an init method and a repeating method that takes an array which makes this a bit cleaner:
extension Array {
init(repeating: [Element], count: Int) {
self.init([[Element]](repeating: repeating, count: count).flatMap{$0})
}
func repeated(count: Int) -> [Element] {
return [Element](repeating: self, count: count)
}
}
let array = [1,2,3].repeated(count: 3) // => [1, 2, 3, 1, 2, 3, 1, 2, 3]
Note that with the new initializer you can get an ambiguous method call if you use it without providing the expected type:
let array = Array(repeating: [1,2,3], count: 3) // Error: Ambiguous use of ‛init(repeating:count:)‛
Use instead:
let array = [Int](repeating: [1,2,3], count: 3) // => [1, 2, 3, 1, 2, 3, 1, 2, 3]
or
let array:[Int] = Array(repeating: [1,2,3], count: 3) // => [1, 2, 3, 1, 2, 3, 1, 2, 3]
This ambiguity can be avoided if you change the method signature to init(repeatingContentsOf: [Element], count: Int) or similar.
With Swift 5, you can create an Array extension method in order to repeat the elements of the given array into a new array. The Playground sample code below shows a possible implementation for this method:
extension Array {
func repeated(count: Int) -> Array<Element> {
assert(count > 0, "count must be greater than 0")
var result = self
for _ in 0 ..< count - 1 {
result += self
}
return result
}
}
let array = [20, 11, 87]
let newArray = array.repeated(count: 3)
print(newArray) // prints: [20, 11, 87, 20, 11, 87, 20, 11, 87]
If needed, you can also create an infix operator to perform this operation:
infix operator **
extension Array {
func repeated(count: Int) -> Array<Element> {
assert(count > 0, "count must be greater than 0")
var result = self
for _ in 0 ..< count - 1 {
result += self
}
return result
}
static func **(lhs: Array<Element>, rhs: Int) -> Array<Element> {
return lhs.repeated(count: rhs)
}
}
let array = [20, 11, 87]
let newArray = array ** 3
print(newArray) // prints: [20, 11, 87, 20, 11, 87, 20, 11, 87]
You can use modulo operations for index calculations of your base collection and functional programming for this:
let base = [1, 2, 3]
let n = 3 //number of repetitions
let r = (0..<(n*base.count)).map{base[$0%base.count]}
You can create a custom overload for the * operator, which accepts an array on the left and an integer on the right side.
func * <T>(left: [T], right: Int) -> [T] {
return (0..<(right*left.count)).map{left[$0%left.count]}
}
You can then use your function just like in python:
[1, 2, 3] * 3
// will evaluate to [1, 2, 3, 1, 2, 3, 1, 2, 3]
Solution 1:
func multiplerArray(array: [Int], time: Int) -> [Int] {
var result = [Int]()
for _ in 0..<time {
result += array
}
return result
}
Call this
print(multiplerArray([1,2,3], time: 3)) // [1, 2, 3, 1, 2, 3, 1, 2, 3]
Solution 2:
let arrays = Array(count:3, repeatedValue: [1,2,3])
// [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
var result = [Int]()
for array in arrays {
result += array
}
print(result) //[1, 2, 3, 1, 2, 3, 1, 2, 3]

Writing an iterator for a 2D array

I am trying to write an iterator for a 2D array. The following is what I have come up with.
def rowsTest() {
val array = Array(
Array(9, 11, 4, 89),
Array(7, 62, 34, 2),
Array(3, 4, 5, 12),
Array(13, 4, 5, 12),
Array(3, 24, 5, 12),
Array(3, 4, 35, 12)
)
def rows: Iterator[Iterator[Int]] = {
new Iterator[Iterator[Int]] {
private var rowIndex = 0
def hasNext: Boolean = rowIndex < 6
def next: Iterator[Int] = {
val rowIterator = new Iterator[Int] {
private var columnIndex = 0
def next: Int = {
val p = array(columnIndex)(rowIndex)
columnIndex += 1
println("ColIndex = "+ columnIndex.toString)
p
}
def hasNext: Boolean = columnIndex < 4
}
rowIndex += 1
println("RowIndex = "+ rowIndex.toString)
rowIterator
}
}
}
for(row <- rows; elem <- row)
println(elem)
}
The above code when run skips the first row, and also gives an ArrayIndexOutOfBoundsException when all elements have been printed. Can you help me figure out where I've gone wrong?
Thank you,
Siddharth Raina.
How about the following code?
val array = Array(Array(1,2,3),Array(4,5,6),Array(7,8,9))
array.view.flatten.iterator
It works, as tested in REPL. Though I don't know if I achieve what I intended with "view". Any comments are welcome.
Edit
I forgot the author wanted a nested iterator.
array.iterator.map(_.iterator)
This certainly works without the "view" and without overhead.
I can't tell from your code what you actually want to do.
If you want traverse your array with iterators of iterators, there's already an easy way to do it:
val a2d = Array.tabulate(4,4)((i,j)=>4*i+j)
a2d.iterator.map(_.iterator)
And if you decide you want a single iterator, you can do that too:
a2d.iterator.flatMap(_.iterator)
If you want to traverse columns even though the array is in row-major order, then you have a little more work to do (which I think is what you were trying to do, but you mixed up your array indices, and maybe some other things):
def iterateColumns(aai: Array[Array[Int]]) = new Iterator[Iterator[Int]] {
private[this] var j = -1
private[this] val shortest = if (aai.length==0) 0 else aai.map(_.length).min
def hasNext = j+1 < shortest
def next = {
j += 1
new Iterator[Int] {
private[this] var i = -1
def hasNext = i+1 < aai.length
def next = {
i += 1
aai(i)(j)
}
}
}
}
Now you can
scala> for (row <- a2d.iterator.map(_.iterator)) println(row.mkString(" "))
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
scala> for (col <- iterateColumns(a2d)) println(col.mkString(" "))
0 4 8 12
1 5 9 13
2 6 10 14
3 7 11 15
(You also ought to be able to do a2d.view.transpose.iterator.map(_.iterator) to avoid making a copy, but unfortunately it doesn't look like this works the way you'd hope in 2.8.1.)
If you want to do it handmade in an imperative style:
def rowsTest() {
val array = Array(
Array(9, 11, 4, 89),
Array(7, 62, 34, 2),
Array(3, 4, 5, 12),
Array(13, 4, 5, 12),
Array(3, 24, 5, 12),
Array(3, 4, 35, 12)
)
def rows: Iterator[Iterator[Int]] = {
new Iterator[Iterator[Int]] {
private var rowIndex = 0
def hasNext: Boolean = rowIndex < 6
def next: Iterator[Int] = {
// fix row index for inner iterator
val rowIdx = rowIndex
val rowIterator = new Iterator[Int] {
private var columnIndex = 0
def next: Int = {
// swap indices!!!
val p = array(rowIdx)(columnIndex)
columnIndex += 1
println("ColIndex = " + columnIndex.toString)
p
}
def hasNext: Boolean = columnIndex < 4
}
rowIndex += 1
println("RowIndex = " + rowIndex.toString)
rowIterator
}
}
}
for (row <- rows; elem <- row)
println(elem)
}
but the
val rows: Iterator[Iterator[Int]] = array.iterator.map(_.iterator)
of ziggystar is still better because its work with non rectangular 2D-arrays too and is more consice and "scalaish".

Resources