How to write a swift function that takes tuples as argument? - sorting

Using Swift 2, I have a dictionary of type [String:String]. Now I want to use the sort method which requires a routine as follows:
mydict.sort(isOrderedBefore: ((String, String), (String, String)) -> Bool)
I assume the two arguments of type (String, String) could be elements of my dictionary. Hence I need two things:
A sort-routine with the requested type that compares the first elements of the two tuples it got as arguments. How do I write this function? I tried the version shown below and others. All produced errors.
fun mysort( (k1,v1):(String,String), (k2,v2):(String,String)) -> Bool {
return k1 > k2
}
How does the compiler know it has to extract two distinct elements from mydict? The call of the sort routine would be:
mydict.sort(mysort)
Looks fairly simple, but.....

let dict = [1:"beta",2:"cecil",3:"alfa"]
let sorted: Array<(Int,String)> = dict.sort { $0.1 < $1.1 } // sorted is an Array<(Int,String)>
print(dict)
// [2: "cecil", 3: "alfa", 1: "beta"]
sorted.forEach { (pair) -> () in
print(pair.0,pair.1)
}
/*
3 alfa
1 beta
2 cecil
*/
let sortingClosureDescendingByVale = { (pair1:( Int, String), pair2:(Int, String)) -> Bool in
pair2.1 < pair1.1
}
let sortedWithClosure = dict.sort(sortingClosureDescendingByVale)
print(sortedWithClosure) // as array of tuple [(2, "cecil"), (1, "beta"), (3, "alfa")]
sortedWithClosure.forEach { (pair) -> () in
print(pair.0,pair.1)
}
/*
2 cecil
1 beta
3 alfa
*/
or if you prefer
let sortingClosureDescendingByVale = { (pair1:(key:Int, value:String), pair2:(key:Int, value:String)) -> Bool in
pair2.value < pair1.value
}
second question: you can ask the same, about sorting Array ...

Related

How to optimize brainf*ck instructions

I'm trying to write an optimisation feature for my brainf*ck interpreter.
It basically combines same instructions into 1 instruction.
I wrote this function but It doesn't work properly:
pub fn optimize_multiple(instructions: &Vec<Instruction>) -> Vec<OptimizedInstruction> {
let mut opt: Vec<OptimizedInstruction> = Vec::new();
let mut last_instruction = instructions.get(0).unwrap();
let mut last_count = 0;
for instruction in instructions.iter() {
if instruction == last_instruction {
last_count += 1;
}
else if let Instruction::Loop(i) = instruction {
opt.push(OptimizedInstruction::Loop(optimize_multiple(i)));
last_count = 1;
}
else {
opt.push(OptimizedInstruction::new(last_instruction.clone(), last_count));
last_instruction = instruction;
last_count = 1;
}
}
opt
}
Here's the OptimizedInstruction enum and the "new" method:
(The Instruction::Loop hand is just a place holder, I didn't used it)
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum OptimizedInstruction {
IncrementPointer(usize),
DecrementPointer(usize),
Increment(usize),
Decrement(usize),
Write,
Read,
Loop(Vec<OptimizedInstruction>),
}
impl OptimizedInstruction {
pub fn new(instruction: Instruction, count: usize) -> OptimizedInstruction {
match instruction {
Instruction::IncrementPointer => OptimizedInstruction::IncrementPointer(count),
Instruction::DecrementPointer => OptimizedInstruction::DecrementPointer(count),
Instruction::Increment => OptimizedInstruction::Increment(count),
Instruction::Decrement => OptimizedInstruction::Decrement(count),
Instruction::Write => OptimizedInstruction::Write,
Instruction::Read => OptimizedInstruction::Read,
Instruction::Loop(_i) => OptimizedInstruction::Loop(Vec::new()),
}
}
}
I ran it with this input:
++-[+-++]
But it gave me this output:
[Increment(2), Loop([Increment(1), Decrement(1)])]
Insted of this:
[Increment(2), Decrement(1), Loop([Increment(1), Decrement(1), Increment(2)])]
I've been trying to solve it for 2 days and still, I don't have any idea about why it doesn't work.
~ Derin
First off, just to rain a little on your parade I just want to point out that Wilfred already made a brainf*ck compiler in Rust that can compile to a native binary through LLVM (bfc). If you are getting stuck, you may want to check his implementation to see how he does it. If you ignore the LLVM part, it isn't too difficult to read through and he has a good approach.
When broken down into its core components, this problem revolves around merging two elements together. The most elegant way I have come across to solve this is use an iterator with a merge function. I wrote an example of what I imagine that would look like below. I shortened some of the variable names since they were a bit long but the general idea is the same. The merge function has a very simple job. When given two elements, attempt to merge them into a single new element. The iterator then handles putting them through that function and returning items once they can no longer be merged. A sort of optional fold if you will.
pub struct MergeIter<I: Iterator, F> {
iter: I,
func: Box<F>,
held: Option<<I as Iterator>::Item>,
}
impl<I, F> Iterator for MergeIter<I, F>
where
I: Iterator,
F: FnMut(&<I as Iterator>::Item, &<I as Iterator>::Item) -> Option<<I as Iterator>::Item>,
{
type Item = <I as Iterator>::Item;
fn next(&mut self) -> Option<Self::Item> {
let mut first = match self.held.take() {
Some(v) => v,
None => self.iter.next()?,
};
loop {
let second = match self.iter.next() {
Some(v) => v,
None => return Some(first),
};
match (self.func)(&first, &second) {
// If merge succeeds, attempt to merge again
Some(v) => first = v,
// If merge fails, store second value for next iteration and return result
None => {
self.held = Some(second);
return Some(first);
}
}
}
}
}
pub trait ToMergeIter: Iterator {
fn merge<F>(self, func: F) -> MergeIter<Self, F>
where
Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Option<Self::Item>;
}
impl<I: Sized + Iterator> ToMergeIter for I {
fn merge<F>(self, func: F) -> MergeIter<Self, F>
where
Self: Sized,
F: FnMut(&Self::Item, &Self::Item) -> Option<Self::Item>,
{
MergeIter {
iter: self,
func: Box::new(func),
held: None,
}
}
}
Then we can apply this process recursively to get our result. Here is a brief example of what that would look like. It isn't quite as memory efficient since it makes a new Vec each time, but it makes the process of specifying what instructions to merge way easier for you and helps make your work easier to read/debug.
pub fn optimize(instructions: Vec<Instruction>) -> Vec<Instruction> {
instructions
.into_iter()
// Recursively call function on loops
.map(|instruction| match instruction {
Instruction::Loop(x) => Instruction::Loop(optimize(x)),
x => x,
})
// Merge elements using the merge iter
.merge(|a, b| {
// State if any two given elements should be merged together or not.
match (a, b) {
(Instruction::IncPtr(x), Instruction::IncPtr(y)) => {
Some(Instruction::IncPtr(x + y))
}
(Instruction::DecPtr(x), Instruction::DecPtr(y)) => {
Some(Instruction::DecPtr(x + y))
}
(Instruction::Increment(x), Instruction::Increment(y)) => {
Some(Instruction::Increment(x + y))
}
(Instruction::Decrement(x), Instruction::Decrement(y)) => {
Some(Instruction::Decrement(x + y))
}
// Etc...
_ => None,
}
})
// Collect results to return
.collect()
}
playground link

Referencing / dereferencing a vector element in a for loop

In the code below, I want to retain number_list, after iterating over it, since the .into_iter() that for uses by default will consume. Thus, I am assuming that n: &i32 and I can get the value of n by dereferencing.
fn main() {
let number_list = vec![24, 34, 100, 65];
let mut largest = number_list[0];
for n in &number_list {
if *n > largest {
largest = *n;
}
}
println!("{}", largest);
}
It was revealed to me that instead of this, we can use &n as a 'pattern':
fn main() {
let number_list = vec![24, 34, 100, 65];
let mut largest = number_list[0];
for &n in &number_list {
if n > largest {
largest = n;
}
}
println!("{}", largest);
number_list;
}
My confusion (and bear in mind I haven't covered patterns) is that I would expect that since n: &i32, then &n: &&i32 rather than it resolving to the value (if a double ref is even possible). Why does this happen, and does the meaning of & differ depending on context?
It can help to think of a reference as a kind of container. For comparison, consider Option, where we can "unwrap" the value using pattern-matching, for example in an if let statement:
let n = 100;
let opt = Some(n);
if let Some(p) = opt {
// do something with p
}
We call Some and None constructors for Option, because they each produce a value of type Option. In the same way, you can think of & as a constructor for a reference. And the syntax is symmetric:
let n = 100;
let reference = &n;
if let &p = reference {
// do something with p
}
You can use this feature in any place where you are binding a value to a variable, which happens all over the place. For example:
if let, as above
match expressions:
match opt {
Some(1) => { ... },
Some(p) => { ... },
None => { ... },
}
match reference {
&1 => { ... },
&p => { ... },
}
In function arguments:
fn foo(&p: &i32) { ... }
Loops:
for &p in iter_of_i32_refs {
...
}
And probably more.
Note that the last two won't work for Option because they would panic if a None was found instead of a Some, but that can't happen with references because they only have one constructor, &.
does the meaning of & differ depending on context?
Hopefully, if you can interpret & as a constructor instead of an operator, then you'll see that its meaning doesn't change. It's a pretty cool feature of Rust that you can use constructors on the right hand side of an expression for creating values and on the left hand side for taking them apart (destructuring).
As apart from other languages (C++), &n in this case isn't a reference, but pattern matching, which means that this is expecting a reference.
The opposite of this would be ref n which would give you &&i32 as a type.
This is also the case for closures, e.g.
(0..).filter(|&idx| idx < 10)...
Please note, that this will move the variable, e.g. you cannot do this with types, that don't implement the Copy trait.
My confusion (and bear in mind I haven't covered patterns) is that I would expect that since n: &i32, then &n: &&i32 rather than it resolving to the value (if a double ref is even possible). Why does this happen, and does the meaning of & differ depending on context?
When you do pattern matching (for example when you write for &n in &number_list), you're not saying that n is an &i32, instead you are saying that &n (the pattern) is an &i32 (the expression) from which the compiler infers that n is an i32.
Similar things happen for all kinds of pattern, for example when pattern-matching in if let Some (x) = Some (42) { /* … */ } we are saying that Some (x) is Some (42), therefore x is 42.

Better way to scan data using scala and spark

Problem
The input data has 2 types of records, lets call them R and W.
I need to traverse this data in Sequence from top to bottom in such a way that if the current record is of type W, it has to be merged with a map(lets call it workMap). If the key of that W-type record is already present in the map, the value of this record is added to it, otherwise a new entry is made into workMap.
If the current record is of type R, the workMap calculated until this record, is attached to the current record.
For example, if this is the order of records -
W1- a -> 2
W2- b -> 3
W3- a -> 4
R1
W4- c -> 1
R2
W5- c -> 4
Where W1, W2, W3, W4 and W5 are of type W; And R1 and R2 are of type R
At the end of this function, I should have the following -
R1 - { a -> 6,
b -> 3 } //merged(W1, W2, W3)
R2 - { a -> 6,
b -> 3,
c -> 1 } //merged(W1, W2, W3, W4)
{ a -> 6,
b -> 3,
c -> 5 } //merged(W1, W2, W3, W4, W5)
I want all the R-type records attached to the intermediate workMaps calculated until that point; And the final workMap after the last record is processed.
Here is the code that I have written -
def calcPerPartition(itr: Iterator[(InputKey, InputVal)]):
Iterator[(ReportKey, ReportVal)] = {
val workMap = mutable.HashMap.empty[WorkKey, WorkVal]
val reportList = mutable.ArrayBuffer.empty[(ReportKey, Reportval)]
while (itr.hasNext) {
val temp = itr.next()
val (iKey, iVal) = (temp._1, temp._2)
if (iKey.recordType == reportType) {
//creates a new (ReportKey, Reportval)
reportList += getNewReportRecord(workMap, iKey, iVal)
}
else {
//if iKey is already present, merge the values
//other wise adds a new entry
updateWorkMap(workMap, iKey, iVal)
}
}
val workList: Seq[(ReportKey, ReportVal)] = workMap.toList.map(convertToReport)
reportList.iterator ++ workList.iterator
}
ReportKey class is like this -
case class ReportKey (
// the type of record - report or work
rType: Int,
date: String,
.....
)
There are two problems with this approach that I am asking help for -
I have to keep track of a reportList - a list of R type records attached with intermediate workMaps. As the data grows, the reportList also grows and I am running into OutOfMemoryExceptions.
I have to combine reportList and workMap records in the same data structure and then return them. If there is any other elegant way, I would definitely consider changing this design.
For the sake of completeness - I am using spark. The function calcPerPartition is passed as argument for mapPartitions on an RDD. I need the workMaps from each partition to do some additional calculations later.
I know that if I don't have to return workMaps from each partition, the problem becomes much easier, like this -
...
val workMap = mutable.HashMap.empty[WorkKey, WorkVal]
itr.scanLeft[Option[(ReportKey, Reportval)]](
None)((acc: Option[(ReportKey, Reportval)],
curr: (InputKey, InputVal)) => {
if (curr._1.recordType == reportType) {
val rec = getNewReportRecord(workMap, curr._1, curr._2)
Some(rec)
}
else {
updateWorkMap(workMap, curr._1, curr._2)
None
}
})
val reportList = scan.filter(_.isDefined).map(_.get)
//workMap is still empty after the scanLeft.
...
Sure, I can do a reduce operation on the input data to derive the final workMap but I would need to look at the data twice. Considering that the input data set is huge, I want to avoid that too.
But unfortunately I need the workMaps at a latter step.
So, is there a better way to solve the above problem? If I can't solve problem 2 at all(according to this), is there any other way I can avoid storing R records(reportList) in a list or scan the data more than once?
I don't yet have a better design for the second question - if you can avoid combining reportList and workMap into a single data structure but we can certainly avoid storing R type records in a list.
Here is how we can re-write the calcPerPartition from the above question -
def calcPerPartition(itr: Iterator[(InputKey, InputVal)]):
Iterator[Option[(ReportKey, ReportVal)]] = {
val workMap = mutable.HashMap.empty[WorkKey, WorkVal]
var finalWorkMap = true
new Iterator[Option[(ReportKey, ReportVal)]](){
override def hasNext: Boolean = itr.hasNext
override def next(): Option[(ReportKey, ReportVal)] = {
val curr = itr.next()
val iKey = curr._1
val iVal = curr._2
val eventKey = EventKey(openKey.date, openKey.symbol)
if (iKey.recordType == reportType) {
Some(getNewReportRecord(workMap, iKey, iVal))
}
else {
//otherwise update the generic interest map but don't accumulate anything
updateWorkMap(workMap, iKey, iVal)
if (itr.hasNext) {
next()
}
else {
if(finalWorkMap){
finalWorkMap = false //because we want a final only once
Some(workMap.map(convertToReport))
}
else {
None
}
}
}
}
}
}
Instead of storing results in a list, we defined an iterator. That solved most of the memory issues we had around this issue.

Type 'Double' does not conform to protocol 'Sequence Type'

This is my code and I don't know why it's not working. The title is what the error says. I'm working with Swift in Xcode and the code is supposed to create a function with as many parameters as I tell it to have/unlimited.
func addMyAccountBalances(balances : Double) -> Double {
var result : Double = 0
for balance in balances {
result += balance
}
}
the code is supposed to create a function with as many parameters as i tell it
What you probably want is a function taking a variable number of arguments,
this is indicated by ... following the type:
func addMyAccountBalances(balances : Double ...) -> Double {
var result : Double = 0
for balance in balances {
result += balance
}
return result
}
print(addMyAccountBalances(1.0, 2.0, 3.0))
print(addMyAccountBalances(4.5, 5.6))
Inside the function, balances has the array type [Double] so that
you can iterate over its elements.
Note that this can be written more compactly with reduce():
func addMyAccountBalances(balances : Double ...) -> Double {
let result = balances.reduce(0.0, combine: +)
return result
}
Your code does not compile because balances : Double is just
a double number, not an array or sequence.

sorted function in Swift 2

I'm sorting an Array like this:
var users = ["John", "Matt", "Mary", "Dani", "Steve"]
func back (s1:String, s2:String) -> Bool
{
return s1 > s2
}
sorted(users, back)
But I'm getting this error
'sorted' is unavailable: call the 'sort()' method on the collection
What should be the correct way to use the sort() method here?
Follow what the error message is telling you, and call sort on the collection:
users.sort(back)
Note that in Swift 2, sorted is now sort and the old sort is now sortInPlace, and both are to be called on the array itself (they were previously global functions).
Be careful, this has changed again in Swift 3, where sort is the mutating method, and sorted is the one returning a new array.
Another way to use closure is:
var numbers = [2,4,34,6,33,1,67,20]
var numbersSorted = numbers.sort( { (first, second ) -> Bool in
return first < second
})
Another way is to use closure in a simple way:
users.sort({a, b in a > b})
In swift 2.2 there are multiple ways we can use closures with sort function as follows.
Consider the array
var names:[String] = ["aaa", "ddd", "rrr", "bbb"];
The different options for sorting the array with swift closures are as added
Option 1
// In line with default closure format.
names = names.sort( { (s1: String, s2: String) -> Bool in return s1 < s2 })
print(names)
Option 2
// Omitted args types
names = names.sort( { s1, s2 in return s1 > s2 } )
print(names)
Option 3
// Omitted args types and return keyword as well
names = names.sort( { s1, s2 in s1 < s2 } )
print(names)
Option 4
// Shorthand Argument Names(with $ symbol)
// Omitted the arguments area completely.
names = names.sort( { $0 < $1 } )
print(names)
Option 5
This is the most simple way to use closure in sort function.
// With Operator Functions
names = names.sort(>)
print(names)
var array = [1, 5, 3, 2, 4]
Swift 2.3
let sortedArray = array.sort()
Swift 3.0
let sortedArray = array.sorted()

Resources