trying to make an asterisk triangle in Swift using a while loop - swift

I'm trying to make tan asterisk triangle output in Swift. I HAVE to use a while loop.
I have tried doing a while loop by it's self - no luck
I think I need to nest a while loop with a for loop but not even sure I can do that. Or I may be making this way harder than it needs to be :). Super new to programming...I simply do not know how to add an"*" in the while loop. below is the latest code that I have tried but it's wrong(obviously) any help would be appreciated
let rows = 5
for i in 1...rows{
for j in 1...i{
print("\(j) ", terminator: "")
}
var num_stars = 1
while num_stars <= 5{
print(num_stars)
num_stars += 1
}
print("")
}

Simply :
let rows = 5
var i = 1
while i <= rows {
print(String(repeating: "*", count: i))
i += 1
}
which outputs :
*
**
***
****
*****
This looks prettier to me :
let rows = 5
var i = 0
while i < rows {
let spaces = String(repeating: " ", count: rows - i - 1)
let stars = String(repeating: "*", count: 2 * i + 1)
print(spaces + stars)
i += 1
}
*
***
*****
*******
*********
Or :
while i < rows {
let spaces = String(repeating: " ", count: rows - i - 1)
print(spaces, terminator: "")
if i > 0 {
print("*", terminator: "")
if i < rows - 1 {
let insideTriangleSpaces = String(repeating: " ", count: 2 * (i - 1) + 1)
print(insideTriangleSpaces, terminator: "")
} else {
let insideTriangleStars = String(repeating: "*", count: 2 * (i - 1) + 1)
print(insideTriangleStars, terminator: "")
}
}
print("*")
i += 1
}
*
* *
* *
* *
*********

Related

How to convert 'String.Element' to 'Int'?

var numsInStr = "1abc2x30yz67"
var sum = 0
for i in numsInStr {
if i.isNumber == true {
sum += i
}
}
print(sum)
Problem is in if statemt to summing numbers. And it returns - "Cannot convert value of type 'String.Element' (aka 'Character') to expected argument type 'Int'"
It is possible to solve this problem like mine. I saw some answers but answers are very short and misunderstanding
Input: 1abc2x30yz67
Output: 100
your solution is not working because you are adding character type in to integrate type value, first you need to convert your character object into string then convert into integer for sum.
hope this may helps you thanks šŸ˜Š
var numsInStr = "1abc2x30yz67"
var sum = 0
for i in numsInStr
{
if i.isNumber == true
{
sum = sum + Int(String(i))
}
}
print(sum)
for sum of all number from your String following is the best solution you will get the sum of 100 as you required in your question.
let numsInStr = "1abc2x30yz67"
.components(separatedBy: .letters)
.compactMap(Int.init)
.reduce(0, +)
print(numsInStr)
What's the issue in sum += i, as the error said, i is a Character, and sum a Int.
Can you make addition between bananas & apples? It's the same logic here.
So you might want to have its Int equivalent with Int(i)
It's returning an optional value, because there is no guarantee that i is valid. You check isNumber before hand, but the line itself doesn't know that. So you can soft unwrap, or if you are sure force unwrap:
sum += Int(String(i))! //Char -> String -> Int
Because there is a String.init(someChar), and Int.init(someString), but not Int.init(someChar), that's why there is the double init().
BUT, keeping your logic, you are iterating characters per characters...
So, in the end you have:
1 + 2 + 3 + 0 + 6 + 7 (ie 19), not 1 + 2 + 30 + 67 (ie 100) as expected.
So if you want to iterate, you need to "group" the consecutive numbers...
With basic for loops, your can do this (it's a possible solution, might no be the better one, but a working one)
let numsInStr = "1abc2x30yz67"
var lastWasNumber = false
var intStrings: [String] = []
for aCharacter in numsInStr {
if aCharacter.isNumber {
if !lastWasNumber {
intStrings.append(String(aCharacter))
} else {
intStrings[intStrings.count - 1] = intStrings[intStrings.count - 1] + String(aCharacter)
}
lastWasNumber = true
} else {
lastWasNumber = false
}
print("After processing: \(aCharacter) - got: \(intStrings)")
}
print(intStrings)
var sum = 0
for anIntString in intStrings {
sum += Int(anIntString)!
}
print("Sum: \(sum)")
At your level, never hesitate to add print() (but never just the variable, always add an additional text which will be context to know from where it's called).
The output being:
$>After processing: 1 - got: ["1"]
$>After processing: a - got: ["1"]
$>After processing: b - got: ["1"]
$>After processing: c - got: ["1"]
$>After processing: 2 - got: ["1", "2"]
$>After processing: x - got: ["1", "2"]
$>After processing: 3 - got: ["1", "2", "3"]
$>After processing: 0 - got: ["1", "2", "30"]
$>After processing: y - got: ["1", "2", "30"]
$>After processing: z - got: ["1", "2", "30"]
$>After processing: 6 - got: ["1", "2", "30", "6"]
$>After processing: 7 - got: ["1", "2", "30", "67"]
$>["1", "2", "30", "67"]
$>100
We rely on Int(someString) (and force unwrapping), but sum += Int(anIntString) ?? 0 should be safer. Since for too big values, if you have "a1234567890123456789123456789123456789" for instance, I'm not sure that Int will be big enough to handle that value. That some edges cases that you need to be aware of.
With high level methods, you can use componentsSeparated(by:) to get an array of only string & only letters. Then, you can filter() (if needed), or compactMap() and transform to Int if possible, then sum (with reduce(into:_:).
As suggested, another solution without keeping a list of String could be:
var sum = 0
var lastWasNumber = false
var currentIntString = ""
for aCharacter in numsInStr {
if aCharacter.isNumber {
if !lastWasNumber {
sum += Int(currentIntString) ?? 0
currentIntString = "" // Reset, but in fact since we override with the next line, it's not necessary to write it
currentIntString = String(aCharacter)
} else {
currentIntString += String(aCharacter)
}
lastWasNumber = true
} else {
lastWasNumber = false
}
print("After processing: \(aCharacter) - got: \(currentIntString) - current sum: \(sum)")
}
sum += Int(currentIntString) ?? 0
print("Sum: \(sum)")
Here, we keep currentInString as a "buffer".
This could be simplified too by removing lastWasNumber and checking instead currentIntString:
var sum = 0
var currentIntString = ""
for aCharacter in numsInStr {
if aCharacter.isNumber {
if currentIntString.isEmpty {
currentIntString = String(aCharacter)
} else {
currentIntString += String(aCharacter)
}
} else {
sum += Int(currentIntString) ?? 0
currentIntString = ""
}
print("After processing: \(aCharacter) - got: \(currentIntString) - current sum: \(sum)")
}
sum += Int(currentIntString) ?? 0
print("Sum: \(sum)")

Is using too many IF statements a problem? SWIFT

I am currently completing a challenge on hacker rank called compare the triplets (https://www.hackerrank.com/challenges/compare-the-triplets/problem), and I was just wondering if using too many IF statements is considered bad programming practice? What are the alternatives other than using switch statements. Please see my code solution below :
import Foundation
func compareTriplets(a: [Int], b: [Int]) -> [Int] {
var compareArray = [0,0]
if a[0] == b[0]{
compareArray[0] = compareArray[0]
}
if a[0] < b[0]{
compareArray[0] = compareArray[0] + 1
}
if a[1] < b[1] {
compareArray[0] = compareArray[0] + 1
}
if a[2] < b[2] {
compareArray[0] = compareArray[0] + 1
}
if a[0] > b[0]{
compareArray[1] = compareArray[1] + 1
}
if a[1] > b[1] {
compareArray[1] = compareArray[1] + 1
}
if a[2] > b[2] {
compareArray[1] = compareArray[1] + 1
}
return compareArray
}
print(compareTriplets(a: [17,28,30], b: [99,28,8]))
This will expand a lot if you will have more and more elements in arrays you send.
Why not try something like
func compareTriplets(a: [Int], b: [Int]) -> [Int] {
var compareArray = [0,0]
if a.count != b.count {
return compareArray
}
for index in 0..<(a.count) {
if a[index] > b[index] {
compareArray[0] += 1
}
else if a[index] < b[index] {
compareArray[1] += 1
}
}
return compareArray
}
Of course, if array lengths can differ then you can take min or go to minimum array length.

The compiler is unable to type-check this expression

I want to divide difference data into 60 and print it as double numbers. When I print it as a string, it does not appear to be a fraction of the number. I get this problem when I print the number "n" . What should I do?
My mistake: the compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
if let date = formatter.date(from: receivedTimeString) {
let receivedTimeHoursMinutes = Calendar.current.component(.hour, from: date) * 60
let receivedTimeMinutes = Calendar.current.component(.minute, from: date)
let totalreceivedTimeMinutes = receivedTimeHoursMinutes + receivedTimeMinutes
let todayHoursMinutes = Calendar.current.component(.hour, from: Date()) * 60
let todayMinutes = Calendar.current.component(.minute, from: Date())
let todayTimeMinutes = todayHoursMinutes + todayMinutes
let difference = todayTimeMinutes - totalreceivedTimeMinutes
let str = String(difference)
switch true {
case difference > 60:
let deger = String(difference / 60)
guard let n = NumberFormatter().number(from: deger) else { return }
print("deger", deger)
self.labelTimerFarkSonuc.text = (n) + (" ") + ("Saattir") + (" ") + (durum)
case difference == 0:
self.labelTimerFarkSonuc.text = (n) + (" ") + ("Dakikadır") + (" ") + (durum)
case difference < 60:
self.labelTimerFarkSonuc.text = (n) + (" ") + ("Dakikadır") + (" ") + (durum)
default:
self.labelTimerFarkSonuc.text = (n) + (" ") + ("Dakikadır") + (" ") + (durum)
}
If i had understood your question correctly,
If you want to have result of following code as decimal fraction,
let deger = String(difference / 60) // Dividing by INT will not give fractions.
Change it to following.
let deger = String(difference / 60.0)

How to get a specific character from index of a string in swift

I am trying to build a Binary to Decimal calculator for the Apple Watch using Swift 4.
The code I am having trouble is this:
var i = 0
var labelInputInt = 0
let labelOutputString = "10010" // Random number in binary
let reverse = String(labelOutputString.reversed()) // Reversing the original string
while i <= reverse.count {
let indexOfString = reverse.index(reverse.startIndex, offsetBy: i)
if reverse[indexOfString] == "1" {
labelInputInt += 2^i * 1
}
i += 1
}
I am using a while loop to get the index indexOfString and check if in the string reverse at the specific index it is equal with "1".
The problem is that I get a runtime error when the if statement is executed.
The error looks like this:
2 libpthread.so.0 0x00007fc22f163390
3 libswiftCore.so 0x00007fc22afa88a0 _T0s18_fatalErrorMessages5NeverOs12Stati
cStringV_A2E4fileSu4lines6UInt32V5flagstFTfq4nnddn_n + 96
4 libswiftCore.so 0x00007fc22afb3323
5 libswiftCore.so 0x00007fc22afdf9a2
6 libswiftCore.so 0x00007fc22aedca19 _T0SS9subscripts9CharacterVSS5IndexVcfg
+ 9
7 libswiftCore.so 0x00007fc22f591294 _T0SS9subscripts9CharacterVSS5IndexVcfg
+ 74139780
8 swift 0x0000000000f2925f
9 swift 0x0000000000f2d402
10 swift 0x00000000004bf516
11 swift 0x00000000004ae461
12 swift 0x00000000004aa411
13 swift 0x0000000000465424
14 libc.so.6 0x00007fc22d88d830 __libc_start_main + 240
15 swift 0x0000000000462ce9
Stack dump:
0. Program arguments: /home/drkameleon/swift4/usr/bin/swift -frontend -inte
rpret tmp/XfwP0oM7FJ.swift -disable-objc-interop -suppress-warnings -module-na
me XfwP0oM7FJ
Illegal instruction (core dumped)
So, how can I get a specific character of a String and compare it with another character without getting this crash?
Your approach to get a specific character from a string is actually correct, there are two other problems in your code:
The index i should run up to and excluding reverse.count.
This is conveniently done with the "half-open range" operator (..<).
^ is the bitwise-xor operator, not exponentiation. Exponentiation is done with the pow() function, in your case
labelInputInt += Int(pow(2.0, Double(i)))
or with the "shift-left" operator << if the base is 2.
So this would be a working variant:
for i in 0 ..< reverse.count {
let indexOfString = reverse.index(reverse.startIndex, offsetBy: i)
if reverse[indexOfString] == "1" {
labelInputInt += 1 << i
}
i += 1
}
But you can simply enumerate the characters of a string in reverse order instead of subscripting (which is also more efficient):
let binaryString = "10010"
var result = 0
for (i, char) in binaryString.reversed().enumerated() {
if char == "1" {
result += 1 << i
}
}
print(result)
Even simpler with forward iteration, no reversed() or << needed:
let binaryString = "10010"
var result = 0
for char in binaryString {
result = 2 * result
if char == "1" {
result += 1
}
}
print(result)
Which suggests to use reduce():
let binaryString = "10010"
let result = binaryString.reduce(0) { 2 * $0 + ($1 == "1" ? 1 : 0) }
print(result)
But why reinvent the wheel? Just use init?(_:radix:) from the Swift standard library (with error-checking for free):
let binaryString = "10010"
if let result = Int(binaryString, radix: 2) {
print(result)
} else {
print("invalid input")
}

Subtracting inputed data in Swift

Good afternoon,
I am having an issue trying to figure out how I take data that was inputed from a textfield and use that data later on in the code. I have attached my code and hopefully I would be able to get some help.
#IBAction func wEnter(sender: AnyObject) {
let number1 = Double(waistText1?.text ?? "") ?? 0
let number2 = Double(waistText2?.text ?? "") ?? 0
let number3 = Double(waistText3?.text ?? "") ?? 0
let number4 = Double(neckText1?.text ?? "") ?? 0
let number5 = Double(neckText2?.text ?? "") ?? 0
let number6 = Double(neckText3?.text ?? "") ?? 0
wavgText.text = String(round(10 * (number1 + number2 + number3) / 3) / 10 ) + " inches"
navgText.text = String((number4 + number5 + number6) / 3) + " inches"
let number7 = Double(wavgText.text! )
let number8 = Double(navgText.text! )
soldBF.text = String(number7 - number8) + "%"
}
Everything seems to be working correctly except for when i try to subtract number7 from number 8. Am i missing something?
if you need anymore details please let me know
It will be better if you switch the order of operations:
let number7 = round(10 * (number1 + number2 + number3) / 3) / 10
let number8 = (number4 + number5 + number6) / 3
wavgText.text = "\(number7) inches"
navgText.text = "\(number8) inches"
soldBF.text = "\(number7 - number8)%"
Then you can see what the problem is.