Swift array for first object in array [duplicate] - arrays

This question already has answers here:
How to find index of list item in Swift?
(23 answers)
Closed 6 years ago.
I have this code in my Roman Numeral conversion algorithm...
for (a, r) in arabicToRomanArray where substring.hasPrefix(r) {
arabic += a
let index = substring.index(substring.startIndex, offsetBy: r.characters.count)
substring = substring.substring(from: index)
break
}
I was wondering if there is an easier way of doing this.
At the moment I am doing a conditional for loop and then breaking on the first entry. Is there a way to do a for first type block with the condition?
The only way I can think of doing it is to filter the array and then get the first object from the filtered array and use that. Seems clunkier than what I'm doing at the moment though.
Edit
After trying out the edit it also makes the algorithm much slower, which makes sense.
The for/break loop will have a best time of O(1) and worst time of O(n).
The filter and first method will have a best time of O(n).

Thanks to #MartinR's comment I found a much better way of doing the same thing.
It's equivalent in time to the for/break loop but less clunky.
The code I had previously...
for (a, r) in arabicToRomanArray where substring.hasPrefix(r) {
arabic += a
let index = substring.index(substring.startIndex, offsetBy: r.characters.count)
substring = substring.substring(from: index)
break
}
Is now...
let (a, r) = arabicToRomanArray[arabicToRomanArray.index(where:{string.hasPrefix($0.1)})!]
arabic += a
let index = substring(substring.startIndex, offsetBy: numCharacters)
substring = substring.substring(from: index)
Using the array function...
array.index(where: (Element) -> Bool)
like...
arabicToRomanArray.index(where:{string.hasPrefix($0.1)})
I also refactored out some of the code into functions once I'd done this so it's actually now...
let (a, r) = findPrefixedArabicToRoman(string: substring)
arabic += a
substring = remove(numCharacters: r.characters.count, fromString: substring)

Related

Kotlin. Merge two list with alternating values [duplicate]

This question already has answers here:
How to combine two different length lists in kotlin?
(6 answers)
Closed 1 year ago.
Is there a ready-made solution for creating an list by alternating elements from two list. I understand how this can be done using loops and conditions, but perhaps there is a ready-made extension that will allow you to solve the problem concisely
You can use zip and flatMap result.
val list1 = listOf(1, 2, 3)
val list2 = listOf(4, 5, 6)
val result = list1.zip(list2).flatMap { pair -> listOf(pair.first, pair.second) }
note that this solution executes extra memory allocation for each pair so my recommendation is still to implement your own version.
fun <T> List<T>.mix(other: List<T>): List<T> {
val first = iterator()
val second = other.iterator()
val list = ArrayList<T>(minOf(this.size, other.size))
while (first.hasNext() && second.hasNext()) {
list.add(first.next())
list.add(second.next())
}
return list
}

What's the fastest way of finding the index of the maximum value in an array?

I have a 2D array of type f32 (from ndarray::ArrayView2) and I want to find the index of the maximum value in each row, and put the index value into another array.
The equivalent in Python is something like:
import numpy as np
for i in range (0, max_val, batch_size):
sims = xp.dot(batch, vectors.T)
# sims is the dot product of batch and vectors.T
# the shape is, for example, (1024, 10000)
best_rows[i: i+batch_size] = sims.argmax(axis = 1)
In Python, the function .argmax is very fast, but I don't see any function like that in Rust. What's the fastest way of doing so?
Consider the easy case of a general Ord type: The answer will differ slightly depending on whether you know the values are Copy or not, but here's the code:
fn position_max_copy<T: Ord + Copy>(slice: &[T]) -> Option<usize> {
slice.iter().enumerate().max_by_key(|(_, &value)| value).map(|(idx, _)| idx)
}
fn position_max<T: Ord>(slice: &[T]) -> Option<usize> {
slice.iter().enumerate().max_by(|(_, value0), (_, value1)| value0.cmp(value1)).map(|(idx, _)| idx)
}
The basic idea is that we pair [a reference to] each item in the array (really, a slice - it doesn't matter if it's a Vec or an array or something more exotic) with its index, use std::iter::Iterator functions to find the maximum value according to the value only (not the index), then return just the index. If the slice is empty None will be returned. Per the documentation, the rightmost index will be returned; if you need the leftmost, do rev() after enumerate().
rev(), enumerate(), max_by_key(), and max_by() are documented here; slice::iter() is documented here (but that one needs to be on your shortlist of things to recall without documentation as a rust dev); map is Option::map() documented here (ditto). Oh, and cmp is Ord::cmp but most of the time you can use the Copy version which doesn't need it (e.g. if you're comparing integers).
Now here's the catch: f32 isn't Ord because of the way IEEE floats work. Most languages ignore this and have subtly wrong algorithms. The most popular crate to provide a total order on Ord (by declaring all NaN to be equal, and greater than all numbers) seems to be ordered-float. Assuming it's implemented correctly it should be very very lightweight. It does pull in num_traits but this is part of the most popular numerics library so might well be pulled in by other dependencies already.
You'd use it in this case by mapping ordered_float::OrderedFloat (the "constructor" of the tuple type) over the slice iter (slice.iter().map(ordered_float::OrderedFloat)). Since you only want the position of the maximum element, no need to extract the f32 afterward.
The approach from #David A is cool, but as mentioned, there's a catch: f32 & f64 do not implement Ord::cmp. (Which is really a pain in your-know-where.)
There are multiple ways of solving that: You can implement cmp yourself, or you can use ordered-float, etc..
In my case, this is a part of a bigger project and we are very careful about using external packages. Besides, I am pretty sure we don't have any NaN values. Therefore I would prefer using fold, which, if you take a close look at the max_by_key source code, is what they have been using too.
for (i, row) in matrix.axis_iter(Axis(1)).enumerate() {
let (max_idx, max_val) =
row.iter()
.enumerate()
.fold((0, row[0]), |(idx_max, val_max), (idx, val)| {
if &val_max > val {
(idx_max, val_max)
} else {
(idx, *val)
}
});
}

Get array elements that fall into a range without error

Is it possible to get elements of the array by slice, if the range goes beyond? for example:
var array = [0,1,2,3,4]
print(array[3...100])
Is there any way to get [3,4]? I need only the part that falls into the range. For example, in Python, I could make an array [3: 100] and get the elements that fall into this range without errors. Maybe there is an analogue in swift?
Because Swift was designed to be safe, so you need to be aware that your code may run into some problem, in swift you can do this?
var bound = 100
if (array.count < 100) {
bound = array.count
}
if (array.count >= 3) {
print(array(3...bound))
}
That's the beauty of the language, you shouldn't do something that is error prone without throwing an error.
You can do this by clamping your initial range (3...100) to the array's indices. However, this doesn't work with ClosedRanges (...), only Ranges.
You can either convert to a Range with Range(3...100), or
You just change your ClosedRange literal to directly be a Range: 3..<101
let array = [0,1,2,3,4]
print(array[(3..<101).clamped(to: array.indices)]) // => [3, 4]
If you do this often enough, you should make an extension for it:
extension Collection {
subscript<R: RangeExpression>(allowingOutOfBoundsRange rangeExpression: R) -> Self.SubSequence
where R.Bound == Self.Index, Self.Indices == Range<Self.Index> {
let range = rangeExpression.relative(to: self)
let clampedRange = range.clamped(to: self.indices)
return self[clampedRange]
}
}
Ideally though, you should just avoid trying to index with out of bounds indices in the first place. Range expressions like 3..., ...3, etc. could be pretty helpful to mitigate most of the need for something like this.

Find the missing element in a given permutation

First, a bit of background:
I'm working on one of the Codility lessons, and, even though this is easy to solve, logistically, it is less than easy to solve, performance-wise.
I've been able to boil it down to just this:
public func solution(_ A : inout [Int]) -> Int {
let B = A // Assigning it to a local speeds it up.
return Array<Int>(Set(B)).sorted(by: {$0<$1}).reduce(0) { ($1 == $0 + 1) ? $1 : $0 } + 1
}
However, this is just a WEE bit too slow. I guess that the main reason is that the reduce goes through ALL elements of an array, even though the answer may be early. I may not be able to speed it up.
But I'd like to try. The part that I'm looking at is this:
.reduce(0) { ($1 == $0 + 1) ? $1 : $0 }
I'm wondering if I can make that comparison more efficient.
I have to check if $1 is equal to $0 + 1. I can't avoid that comparison.
The ternary operator is not actually faster than an if clause, but it looks cooler ;).
Is there a higher-performance way to compare two positive integers for equivalence than the basic "==" operator?
BTW: This is not a "do my homework for me" question. It's pretty legit, and these Codility lessons don't give you credit or anything. They are just a fun exercise. I want to know how to do this, as I'm sure I'll need it in the future.
Using the solution suggested by #TNguyen in comments, below piece of code got 100% on both correctness and performance.
You just need to generate the correct Array, containing each Integer in the range [1..(N + 1)] by calling Array(1...A.count+1). Then you sum its elements using reduce(0,+) and finally substract the sum of the elements of the input array A. The difference between the two sums gives the missing element.
public func solution(_ A : inout [Int]) -> Int {
return Array(1...A.count+1).reduce(0,+)-A.reduce(0,+)
}
An even faster solution is to use the mathematical formula1+2+...+n=n(n-1)/2 for the first sum.
public func solution(_ A : inout [Int]) -> Int {
return (A.count+1)*(A.count+2)/2-A.reduce(0,+)
}
100% score in python using an other concept:
def solution(A):
Index=0;
while (Index<len(A)):
while((A[Index]-1) != Index and A[Index]<=len(A)):
Tmp=A[Index]; #Permut
A[Index]=A[Tmp-1];
A[Tmp-1]=Tmp;
Index+=1;
Index=0;
while Index<len(A):
if((A[Index]-1) != Index) :
return Index+1;
else:
Index+=1;
return len(A)+1;
pass
The idea behind is that for a given permutation, each element A[Index]-1 should match to Index except for the missing element. Elements of the array are then permuted until the correspondence is achieved or not achieved when A[Index]>len(A).

can the keyword "foreach" get the array parameter?

I am a beginner of the scala. many concepts aren't clear for me.
I want to ask that if the foreach can get (or control) the array parameter ?
for example:
val array = Array.ofDim[Double](2,6)
I can use for to control the array's parameter, like
for( i <- 0 until 2){
for(j <- 0 until 6){
......... }}
I can use i,j control and get the parameter. Is "foreach" can do that??
(I know foreach can do things without the parameter, but I just want to ask if it can get
the array parameter?)
thank you :)
I'm not exactly sure what you're asking. If you're asking how to loop over the full array item-by-item, then you can do that without nesting for comprehensions. This will print the contents of your 2D array:
for (row <- array; col <- row) println(col)
If you're asking how to loop over all the indices of the array (I think maybe that's what you mean when you say parameter), then you can use the indices property:
for (i <- array.indices; j <- array(i).indices) println(array(i)(j))
If you're just trying to do indexOf across a 2D array, you can probably just reuse the solution for indexOf for 2D Vector in Scala. This is how I'd adapt it to your code:
val array = Array.tabulate(2,6)(_*6+_)
val searchValue = 8
val indices: Option[(Int, Int)] =
(for {
i <- array.indices
j <- array(i).indices
if (array(i)(j) == searchValue)
} yield (i, j)).headOption
If none of the values match, you'll get indices = None. In this case there is a match, so you get indices = Some((1,2)), because 8 is at array(1)(2).
(Note: Unlike indexOf, using a for comprehension does not short-circuit as soon as it finds the solution. If you make the index ranges lazy by calling .iterator, .view or .toStream then you'll get the expected short-circuiting behavior.)
U can use the function [ indexOf(elem: T): Int ] that will return the position
Scala Array

Resources