Split array into groups of different sizes - ios

I need to split an array into groups of different sizes.
let objects = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
let sizes = [3,2,4]
The output should be [[1,2,3], [4,5], [6,7,8,9], [10,11,12], [13,14], [15]]
What's the easiest way to achieve this?

This is not the exact solution for your problem but to split the array into different sizes you can use something like below:
var index = 0
var count = 0
for size in sizes{
let newArray = objects[index..<size+index]
index = count > 0 ? size + sizes[count-1] : size //index = 3
count = count + 1
print(newArray)
}
This will split array into group of different sizes. You can modify the code to complete all the array elements. This basically loops once over the sizes Array.

Related

Creating a Scale Between 0 and 1 Even when Higher numbers are passed in

I want to write an algorithm which allows me to rescale numbers to between 0 and 1. This means if I pass 25, 100, 500 then it should generate a new scale and represent those numbers on a scale of 0 to 1.
Here is what I have which is incorrect and does not make sense.
height: item.height/item.height * 20
Pass in the numbers in an array.
Loop through the numbers and find the max.
Map the array of integers to an array of Doubles, each one being the value from the source array, divided by the max.
Try to write that code. If you have trouble, update your question with your attempt and tell us what's going wrong.
EDIT:
Your answer shows how to print your resulting scaled values, but you implied that you actually want to create a new array containing the scaled values. For that you could use a function like this:
func scaleArray(_ sourceArray: [Int]) -> [Double] {
guard let max = sourceArray.max() else {
return [Double]()
}
return sourceArray.map {
return Double($0)/Double(max)
}
}
Edit #2:
Here is code that would let you test the above:
func scaleAndPrintArray(_ sourceArray: [Int]) {
let scaledArray = scaleArray(sourceArray)
for index in 0..<sourceArray.count {
print(String(format: "%3d", sourceArray[index]), String(format: "%0.5f",scaledArray[index]))
}
}
for arrayCount in 1...5 {
let arraySize = Int(arc4random_uniform(15)) + 5
var array = [Int]()
for _ in 1..<arraySize {
array.append(Int(arc4random_uniform(500)))
}
scaleAndPrintArray(array)
if arrayCount < 5 {
print("-----------")
}
}
(Sorry but I don't know swift)
If you're wanting to create a linear scale, a linear equation is y(x) = m*x + c. You wish the output to range from 0 to 1 when the input ranges from the minimum value to the maximum (your question is ambiguous, maybe you may wish to lock y(0) to 0).
y(0) = min
y(1) = max
therefore
c = min
m = max - min
and to find the value of any intervening value
y = m*x + c

Random images to (many) Image Views

Sadly, I've got 36 UIImages and need to set a random image to each one.
My 6 images are named;
"Owl1"
"Owl2"
"Owl3"
"Owl4"
"Owl5"
"Owl6"
So, I want to set one random image to my 36 different UIImages. What is the best way to do this? An array? Here's my "try" so far.
var images: [UIImage] = [
UIImage(named: "Owl1")!,
UIImage(named: "Owl2")!,
UIImage(named: "Owl3")!,
UIImage(named: "Owl4")!,
UIImage(named: "Owl5")!,
UIImage(named: "Owl6")!
]
var randomUIImage = [Image1, Image2, Image3, Image4, Image5...]
randomUIImage.shuffleInPlace()
randomUIImage[0].image = images[0]
randomUIImage[1].image = images[1]
But I realized this will not work, and I can't make this code for all 36 images... Anyone got a better idea? ;-)
Tip: you can use a range + map to create an array of your images.
let images = (1...6).map { UIImage(named: "Owl\($0)") }
(1...6) produces a collection of Ints, from 1 to 6 (including 6), and with map we create a new instance of UIImage for each Int, using them for the naming - since you named your images in order, it's convenient. It's like doing a loop and appending a new intance of UIImage to an array inside the loop, using an index for the naming: "Owl1", "Owl2", etc.
If you also have your UIImageViews in an array, you can assign the images with a loop.
Here's an example (I didn't verify on Xcode but it should be close to what you need):
for view in imageViewsArray { // the array with the 36 imageViews
// a random index for the array of 6 images
let randomIndex = Int(arc4random_uniform(UInt32(images.count))
// assign the randomly chosen image to the image view
view.image = images[randomIndex]
}
You can have an array of image names, and an array of images to hold them..
var imageNames:[String] = ["Owl1", "Owl2"....etc]
var owlImages:[UIImage] = []
Then randomly append the images
for index in 0...imageNames.count - 1 {
var randomInt = Int(arc4random_uniform(UInt32(imageNames.count)) //a random int from 0 to the size of your array
owlImages.append(UIImage(named: imageNames[randomInt] //add the random image to the array
}

need to random an array of images and words. Arc4random_uniform

I'm working on a project of shapes and words. I currently have two arrays. One array is of images, the other array is just a set of strings that describes the first array of images. I'm using 4 buttons to display 4 items in the "string" array. Can someone please tell me how can I utilize arc4random but also make sure one of my 4 buttons display the name of the image.
Below is a quick example of my arrays
var myShapes = ["circle", "square", "rectangle"]
var images = ["circle.png", "square.png", "rectangle.png"]
How do I utilize arc4Random but make sure one item from each array always equals each other?
Adding information for the function to randomize my images.
func randomImage() -> UIImage {
let arrayCount = UInt32(myImages.count)
let unsignedRandomNumber = arc4random_uniform(arrayCount)
let randomNumber = Int(unsignedRandomNumber)
return UIImage(named: myImages[randomNumber])!
}
Below is how I'm doing the random text
let randomDisplayText = buttonDisplayText[Int(arc4random_uniform(UInt32(buttonDisplayText.count)))]

Swift - Create variables with different names in a for loop

I am learning Apple Swift with the hope of releasing apps for the iPhone.
There are three different 'modes' to my game: 5 swipes, 10 swipes, or 25 swipes. Let's use 5 swipes as an example. I want a variable to be assigned to each swipe, which will be a random integer within the range 1...100 (inclusive). Obviously it doesn't seem neat when I am creating variables in a long list like this:
var s1 = arc4random_uniform...
var s2 = arc4random_uniform...
Also that could just be a pain when I get to 25 swipes.
So I thought, maybe I could use a 'for' loop. So:
for index(in 1...5) {
//create variable with different name with a random integer
}
So here's where my problem lies... I am unsure how I would create variables with different names. So: s1, s2, s3, s4, and s5.
It would probably be in the form of an algorithm like:
var s(prevnumber+1) = arc4random_uniform....
I will do it this way:
var numElement = 5 // change to 10 or 25 depends on what you need
var array = Array<UInt32>(count: numElement, repeatedValue: 0)
for i in 0 ..< numElement {
array[i] = arc4random_uniform(100)
}
Then to access the first variable, you can do
array[0]
And it will give you the random number

F# lazy pixels reading

I want to make a lazy loading of image pixels to the 3 dimensional array of integers.
For example in simple way it looks like this:
for i=0 to Width
for j=0 to Height
let point=image.GetPixel(i,j)
pixels.[0,i,j] <- point.R
pixels.[1,i,j] <- point.G
pixels.[2,i,j] <- point.B
How it can be made in lazy way?
What would be slow is the call to GetPixel. If you want to call it only as needed, you could use something like this:
open System.Drawing
let lazyPixels (image:Bitmap) =
let Width = image.Width
let Height = image.Height
let pixels : Lazy<byte>[,,] = Array3D.zeroCreate 3 Width Height
for i = 0 to Width-1 do
for j = 0 to Height-1 do
let point = lazy image.GetPixel(i,j)
pixels.[0,i,j] <- lazy point.Value.R
pixels.[1,i,j] <- lazy point.Value.G
pixels.[2,i,j] <- lazy point.Value.B
pixels
GetPixel will be called at most once for every pixel, and then reused for the other components.
Another way of approaching this problem would be to do a bulk-load of the entire image. This will be a lot quicker than calling GetPixel over and over again.
open System.Drawing
open System.Drawing.Imaging
let pixels (image:Bitmap) =
let Width = image.Width
let Height = image.Height
let rect = new Rectangle(0,0,Width,Height)
// Lock the image for access
let data = image.LockBits(rect, ImageLockMode.ReadOnly, image.PixelFormat)
// Copy the data
let ptr = data.Scan0
let stride = data.Stride
let bytes = stride * data.Height
let values : byte[] = Array.zeroCreate bytes
System.Runtime.InteropServices.Marshal.Copy(ptr,values,0,bytes)
// Unlock the image
image.UnlockBits(data)
let pixelSize = 4 // <-- calculate this from the PixelFormat
// Create and return a 3D-array with the copied data
Array3D.init 3 Width Height (fun i x y ->
values.[stride * y + x * pixelSize + i])
(adopted from the C# sample on Bitmap.LockBits)
What do you mean by lazy?
An array is not a lazy data type, which means that if you want to use arrays, you need to load all pixels during the initialization. If we were using single-dimensional array, an alternative would be to use seq<_> which is lazy (but you can access elements only sequentially). There is nothing like seq<_> for multi-dimensional arrays, so you'll need to use something else.
Probably the closest option would be to use three-dimensional array of lazy values (Lazy<int>[,,]). This is an array of delayed thunks that access pixels and are evaluated only when you actually read the value at the location. You could initialize it like this:
for i=0 to Width
for j=0 to Height
let point = lazy image.GetPixel(i,j)
pixels.[0,i,j] <- lazy point.Value.R
pixels.[1,i,j] <- lazy point.Value.G
pixels.[2,i,j] <- lazy point.Value.B
The snippet creates a lazy value that reads the pixel (point) and then three lazy values to get the individual color components. When accessing color component, the point value is evaluated (by accessing Value).
The only difference in the rest of your code is that you'll need to call Value (e.g. pixels.[0,10,10].Value to get the actual color component of the pixel.
You could define more complex data structures (such as your own type that supports indexing and is lazy), but I think that array of lazy values should be a good starting point.
As mentioned already by other comments that you can use the lazy pixel loading in the 3D array but that would just make the GetPixel operation lazy and not the memory allocation of the 3D array as the array is allocated already when you call create method of Array3D.
If you want to make the memory allocation as well as GetPixel lazy then you can use sequences as shown by below code:
let getPixels (bmp:Bitmap) =
seq {
for i = 0 to bmp.Height-1 do
yield seq {
for j = 0 to bmp.Width-1 do
let pixel = bmp.GetPixel(j,i)
yield (pixel.R,pixel.G,pixel.B)
}
}

Resources