12 Replies
      Latest reply on Aug 21, 2019 1:34 AM by Claude31
      Steadi18 Level 1 Level 1 (0 points)

        Hello people

         

        I recently began my attempt at learning Swift using the Apple tutorial book and playgrounds. I have no experience with Swift or in programming, so it’s been a steep hill, but still, it’s been interesting.

         

        However, I’ve now reached a point where I can’t seem to find the answers for an exercise in the Apple playground;  the exercise – Counting Votes.

         

        First issue: The calculation in my loop seems to be off.

         

        the loop in question:

         

        var yesVotes = [0]

        var noVotes = [0]

         

        for vote in shouldMascotChangeVotes {

            if vote == true {

                yesVotes += [1]

            } else {

                vote == false

                noVotes += [1]

                }

        }

        yesVotes.count

        noVotes.count

         

        The array supplied by Apple to the exercise only has 200 votes, yet my loop calculation returns a total of 202 votes. I can't see where the extra votes comes from?

         

        Second issue:

        according to the exercise, the next step is to write a function that takes two arguments, forIssue as a String and withVotes as Bool. The result of printResults should be “Should we change mascot? 54 yes, 23 no”.

         

        So, my attempt at the function so far is thus:

         

        func results(forIssue: String, withVotes: Bool) -> String {

         

            for vote in withVotes {

                if vote == true {

                    yesVotes += [1]

                } else {

                    vote == false

                    noVotes += [1]

                }

        }

         

        }

         

        I'm pretty certain the function is wrong in a bunch of places and still not finished, but my question is primarily that I don't understand the error-message for the for vote in withVotes line. The message reads "Type 'Bool' does not conform to protocol 'Sequence'... Any explanation on this would be greatly appreciated!

         

        Also, thank you very much for all the explanations in many other questions that have helped me in my attempts so far!

         

        Cheers

         

         

        (also, if this question is in the wrong forum, sorry about that)

        • Re: Newbie questions on Swift-exercise
          QuinceyMorris Level 8 Level 8 (6,050 points)

          On the first problem, you're doing something unnecessarily, which results in accidentally doing it wrong. When you declare yesVotes like this:

           

          var yesVotes = [0]
          

           

          you're declaring an array of Int values, and you set the first one to the value 0. Ditto noVotes. Then you append 200 votes either to yesVotes or noVotes, for a total of 200 + 1 + 1 = 202, because you started with an "extra" value in each array. You could fix this by starting with empty arrays, declared in one of these ways (among others):

           

          var yesVotes: [Int] = [] // or ...
          var yesVotes = [] as [Int]
          

           

          You have to say what it's an array of, because [ ] is an empty array, but the compiler doesn't know what kind of values you intend.

           

          However, the unnecessary part is that you don't need to use an array, since you just need the vote count, so you can do this:

           

          var yesVotes = 0
          var noVotes = 0
          
          for vote in shouldMascotChangeVotes {
              if vote { // == true is unnecessary, this means the same thing
                  yesVotes += 1
              } else {
                  //vote == false ... you don't need this, it doesn't do anything
                  noVotes +=1
                  }
          }
          print (yesVotes)
          print (noVotes)
          

           

          On the second problem, the second parameter is a true/false value, not an array. The "for…in" construct is for iterating through an array (or some other kind of Sequence, hence that error message). I'm not sure exactly what's intended, but the fact that "withVotes" is plural suggests you should declare the function like this:

           

          func results(forIssue: String, withVotes: [Bool]) -> String // 2nd parameter is array of Bool
          

           

          and you would, of course, need the same counting fix as in the first problem, inside the body of the function.

            • Re: Newbie questions on Swift-exercise
              Steadi18 Level 1 Level 1 (0 points)

              Thank you! The loop finally returns a correct number of votes

               

              however, the function started to just run and run. At least 500000 times before I stopped it. Which seems massive and slowing the Playground down to almost useless. And then, suddenly it stopped doing that again. Now nothing happens. Extremes, I guess.

               

              my function;

               

              func Results(forIssue: String, withVotes: [Bool]) -> String {

               

               

                  var yesVotes = 0

                  var noVotes = 0

               

                  for vote in withVotes {

                      if vote {

                          yesVotes += 1

                      } else {

                          noVotes += 1

                      }

                  }

               

                  print(yesVotes)

                  print(noVotes)

               

                  return ""

              }



              I've tried changing the withVotes with shouldMascotChangeVotes and this still doesn't move the function in any way. Also, yes, fully aware that the return line is wrong but I'll look into that when I understand the behaviour above it.


                • Re: Newbie questions on Swift-exercise
                  goldsdad Level 4 Level 4 (585 points)

                  Please show all the code so we see how you create the array of votes that you pass to the function and the context in which the function is called.

                  (By the way, the conventional way to name a function in Swift is to make the first letter lower case, as you did in your first post.)

                    • Re: Newbie questions on Swift-exercise
                      Steadi18 Level 1 Level 1 (0 points)

                      The array is one already created by Apple for the exercise, which is why I never thought about including it here. That would have been a good idea, I see now.

                       

                      However, last night brought a solution, not least due to the suggestions in this thread.

                       

                      If anyone is interested, the function ended up like this: (with a first letter lower case )

                       

                      func results(forIssue: String, withVotes: [Bool]) -> String {

                        

                          var yesVotes = 0

                          var noVotes = 0

                        

                          for vote in withVotes {

                              if vote {

                                  yesVotes += 1

                              } else {

                                  noVotes += 1

                              }

                      }

                          print(yesVotes)

                          print(noVotes)

                        

                          return "\(forIssue)" + " " + "\(yesVotes)" + " " + "yes" + " " + "\(noVotes)" + " " + "no"

                      }

                      results(forIssue: "should we change mascot?", withVotes: shouldMascotChangeVotes)

                      print(results(forIssue: "should we change mascot?", withVotes: shouldMascotChangeVotes))

                        • Re: Newbie questions on Swift-exercise
                          ArminiusA Level 1 Level 1 (0 points)

                          Was pretty confused about the forIssue string and the withVotes declarations. Your reply put me on track. Somehow had the issue of votes not clearing after each poll so..

                           

                          func tallyResults(forIssue:String, withVotes: [Bool]) {

                              let totalVotes = withVotes.count

                              for voteIssue in withVotes {

                                  if voteIssue==true {

                                      yesVotes += 1

                                  } else {

                                      noVotes += 1

                                  }

                              }

                              if yesVotes > noVotes {

                                  print("\(forIssue) passed with \(yesVotes) votes for and \(noVotes) against.\n Yes: \(yesVotes). No: \(noVotes). Total Votes: \(totalVotes)")

                              } else {

                                  print("\(forIssue) did not pass with \(noVotes) votes against and \(yesVotes) for.\n Yes: \(yesVotes). No: \(noVotes). Total Votes: \(totalVotes)")

                              }

                              // Clear vote results to prevent double counting

                              yesVotes = 0

                              noVotes = 0

                          }

                          tallyResults(forIssue: "Should we change the mascot", withVotes: shouldMascotChangeVotes)

                          tallyResults(forIssue: "Should we install coffee vending machines", withVotes: shouldInstallCoffeeVendingMachineVotes)

                          tallyResults(forIssue: "Should we have more poll options vote", withVotes: shouldHaveMorePollOptionsVotes)

                            • Re: Newbie questions on Swift-exercise
                              manacus Level 1 Level 1 (0 points)

                              Thanks that was useful, helped me with a couple of mistakes.

                              I think you've still got some unnecessary steps though. You don't need to count because for ... in will automatically stop at end of array. Also you don't need to escape or put in quotes forIssue when printing because it's already a String.

                              My version:

                               

                               

                              var yesVotes = 0
                              var noVotes = 0
                              
                              func printResults(forIssue issue: String, withVotes votes: [Bool]) {
                                  for vote in votes {
                                      if vote {
                                          yesVotes += 1
                                      } else {
                                          noVotes += 1
                                      }
                                  }
                                      print(issue + " \(yesVotes)"  + " yes, " + " \(noVotes)" + " no ")
                                  yesVotes = 0
                                  noVotes = 0
                              }
                              
                              printResults(forIssue: "Should we change the mascot?", withVotes:shouldMascotChangeVotes)
                              printResults(forIssue: "Should we install coffee vending machines?", withVotes:shouldInstallCoffeeVendingMachineVotes)
                              printResults(forIssue: "Should we have more poll options?", withVotes:shouldHaveMorePollOptionsVotes)
                              
                              // prints: Should we change the mascot? 125 yes,  75 no 
                              // prints: Should we install coffee vending machines? 100 yes,  100 no 
                              // prints: Should we have more poll options? 74 yes,  126 no 
                              
                      • Re: Newbie questions on Swift-exercise
                        yoamod Level 1 Level 1 (0 points)

                        Hi. This may seem like a really stupid question but I am a complete newbie to Swift and programming in general.

                         

                        How does the yesVotes know to count the trues and visa versa?

                          • Re: Newbie questions on Swift-exercise
                            Claude31 Level 8 Level 8 (6,925 points)

                            Votes is an array of Bool, either true or false.

                             

                            the loop:

                             

                                for vote in votes {
                                    if vote {
                                        yesVotes += 1
                                    } else {
                                        noVotes += 1
                                    }
                                }
                            

                             

                            explores all the votes in the array.

                            If the vote is true (yes), then add 1 to yesVotes counter, otherwise adds 1 to noVotes.

                             

                            You have dedicated Swift functions to do it directly : reduce.

                             

                            It works like this:

                            let votes = [true, false, false, true, true, true]
                            let yesVotes = votes.reduce(0, { $0 + ($1 ? 1 : 0) })
                            print(yesVotes)
                            

                             

                            Which is a bit cryptic at first but convenient.

                             

                            Look here for other solutions :

                            h ttps://stackoverflow.com/questions/39984933/how-can-i-find-a-number-of-true-statements-in-an-array-of-bools-in-swift

                              • Re: Newbie questions on Swift-exercise
                                eskimo Apple Staff Apple Staff (12,295 points)

                                You have dedicated Swift functions to do it directly : reduce.

                                reduce is a super useful technique but here it just complicates things.  In this case it’d be better to use filter.  For example:

                                let votes = [true, false, false, true, true, true]
                                let yesVotes = votes.filter{ $0 }.count
                                print(yesVotes)

                                Share and Enjoy

                                Quinn “The Eskimo!”
                                Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                                let myEmail = "eskimo" + "1" + "@apple.com"

                          • Re: Newbie questions on Swift-exercise
                            SwiftlyAdam Level 1 Level 1 (0 points)

                            Here is the way I did it:

                             

                            var yes = 0

                            var no = 0

                            for vote in shouldMascotChangeVotes {

                                if vote {

                                yes += 1

                                } else {

                                    no += 1

                                }

                            }

                            print(yes)

                            print(no)

                            if yes > no{

                                print("Your bill passed!")

                            } else if yes < no {

                                print("This one failed!")

                            } else {

                                print("It's a tie!  We need one more vote!")

                            }