Zephir Language Parse Exception - zephir

I am trying to compile the below code in zephir language and it gives me Parse error.
I am not sure what am I doing wrong.
public static function calculateDiscrepancy(tpImpr, liImpressions, defaults) {
var numeratorx = 1-(tpImpr + defaults);
if numeratorx != 0 && liImpressions != 0 {
return (double)(numeratorx / liImpressions) * 100;
}else{
return 0;
}
}
Error
Zephir\ParseException: Syntax error in /var/www/vhosts/app/advertisingcalculator.zep on line 58
var numeratorx = 1-(tpImpr + defaults);
-----------------------^
Any Ideas?

You can try this:
let numeratorx = 1 - (tpImpr + defaults);
Edit: removed asterisks. Leave a space between 1 and the operator -, and another space between the operator - and the left parenthesis (.
var is only for declarations and the value must be static, then you can set a dynamic value with let:
var numeratorx; // or var numeratorx = 1;
let numeratorx = 1 - (tpImpr + defaults);

Related

no response on stdout HackerRank Swift

Hello i practice on hackerRank using swift and now i have a problem. My code works great in swift playground, and return the expected result, but in HackerRank i have runtime error ~ no response on stdout ~ I've tried to reset code and refresh page. What could be the problem?
func diagonalDifference(arr: [[Int]]) -> Int {
// Write your code here
let rowNumber = arr[0][0]
var leftD = 0
var rightD = 0
for i in 1...rowNumber {
leftD += arr[i][i - 1]
}
var increasedNum = 0
for i in (1...rowNumber).reversed() {
rightD += arr[i][increasedNum]
increasedNum += 1
}
var absoluteDifference = leftD - rightD
if absoluteDifference < 0 {
absoluteDifference = absoluteDifference * -1
}
return absoluteDifference
}
Here is the challenge page:
https://www.hackerrank.com/challenges/diagonal-difference/problem
Your problem is a misunderstanding of what is passed to your diagonalDifference() function. The code which calls that function uses the first line of input to correctly size the array, but that value is not passed to your function in arr[0][0]. Instead, you should use arr.count to determine the dimensions of the array, then you should be indexing the array as 0..<arr.count.
To fix your code
change:
let rowNumber = arr[0][0]
to:
let rowNumber = arr.count
change:
leftD += arr[i][i - 1]
to:
leftD += arr[i][i]
And change both instances of
1...rowNumber
to:
0..<rowNumber
func diagonalDifference(arr: [[Int]]) -> Int {
var difference = 0
for i in 0..<arr.count {
difference += (arr[i][i] - arr[i][arr.count-1-i])
}
return Int(abs(difference))
}

Add / subtract characters as Int in Swift

I need to implement an algorithm to check if an input is valid by calculating a modulo of a String.
The code in Kotlin:
private val facteurs = arrayOf(7, 3, 1)
private fun modulo(s: String): Int {
var result = 0
var i = -1
var idx = 0
for (c in s.toUpperCase()) {
val value:Int
if (c == '<') {
value = 0
} else if (c in "0123456789") {
value = c - '0'
} else if (c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ") {
value = c.toInt() - 55
} else {
throw IllegalArgumentException("Unexpected character: $c at position $idx")
}
i += 1
result += value * facteurs[i % 3]
idx += 1
}
return result % 10
}
This implies doing math operations on the characters.
Is there an elegant way to do this in Swift 3 and 4?
I tried some cumbersome constructs like this :
value = Int(c.unicodeScalars) - Int("0".first!.unicodeScalars)
But it does not even compile.
I'm currently using Swift 4 with XCode9, but Swift3 answer is welcome too.
You can enumerate the unicodeScalars view of a string together
with the running index, use switch/case pattern matching,
and access the numeric .value of the unicode scalar:
func modulo(_ s: String) -> Int? {
let facteurs = [7, 3, 1]
var result = 0
for (idx, uc) in s.uppercased().unicodeScalars.enumerated() {
let value: UInt32
switch uc {
case "<":
value = 0
case "0"..."9":
value = uc.value - UnicodeScalar("0").value
case "A"..."Z":
value = uc.value - UnicodeScalar("A").value + 10
default:
return nil
}
result += Int(value) * facteurs[idx % facteurs.count]
}
return result % 10
}
This compiles with both Swift 3 and 4. Of course you could also
throw an error instead of returning nil for invalid input.
Note that "<", "0", "9" etc.
in the switch statement are inferred from the context as UnicodeScalar,
not as String or Character, therefore "0"..."9" (in this context)
is a ClosedRange<UnicodeScalar> and uc can be matched against
that range.
Something like this works for me:
"A".utf16.first! + 2 //comes out to 67
Careful with the forced unwrap "!"
If you need the scalars value you can do
"A".unicodeScalars.first!.value + 2
More reading can be done on this here in the SPL.
For the c Character type value you could do this:
String(c).unicodeScalars.first!.value + 2
Here is an attempt to mod the function:
func modulo(s: String) -> Int? {
var result = 0
var factors = [7,3,1]
for (i, c) in s.uppercased().characters.enumerated() {
let char = String(c)
var val: Int
if char == "<" {
val = 0
} else if "0123456789".contains(char) {
val = Int(char.unicodeScalars.first!.value - "0".unicodeScalars.first!.value)
} else if "ABCDEFGHIJKLMNOPQRSTUVWXYZ".contains(char) {
val = Int(char.unicodeScalars.first!.value - 55)
} else {
return nil
}
result += val * factors[(i) % 3]
}
return result % 10
}
This is in swift 3...in 4 I believe you can just iterate over the string without converting to Chars

Swift Type 'string.index' has no subscript members

I'm currently converting C++ code to Swift and I've gotten stuck on one part. The parameter passed into the function is a string and the area where I'm stuck is when attempting to set a variable based on the second to last character of a string to check for a certain character.
The error shows up on this line:
line[i-1]
I've tried casting this value to an Int but this didn't work:
Int(line[i - 1])
I've also tried to see if the string's startIndex function which takes a Int would work but it didn't:
line.startIndex[i - 1]
Here is the full function:
func scanStringForSpecificCharacters(line: String){
var maxOpen: Int = 0;
var minOpen: Int = 0;
minOpen = 0;
maxOpen = 0;
var i = 0
while i < line.characters.count {
for character in line.characters {
//var c: Character = line[i];
if character == "(" {
maxOpen += 1;
if i == 0 || line[i - 1] != ":" {
minOpen += 1;
}
}
else if character == ")"{
minOpen = max(0,minOpen-1);
if i == 0 || line[i-1] != ":"{
maxOpen -= 1;
}
if maxOpen < 0{
break;
}
}
}
if maxOpen >= 0 && minOpen == 0{
print("YES")
}else{
print("NO")
}
}
}
Strings in Swift aren't indexed collections and instead you can access one of four different views: characters, UTF8, UTF16, or unicodescalars.
This is because Swift supports unicode, where an individual characters may actually be composed of multiple unicode scalars.
Here's a post that really helped me wrap my head around this: https://oleb.net/blog/2016/08/swift-3-strings/
Anyway, to answer you question you'll need to create an index using index(after:), index(before:), or index(_, offsetBy:).
In your case you'd want to do something like this:
line.index(line.endIndex, offsetBy: -2) // second to last character
Also, you'll probably find it easier to iterate directly using a String.Index type rather than Int:
let line = "hello"
var i = line.startIndex
while i < line.endIndex {
print(line[i])
i = line.index(after: i)
}
// prints ->
// h
// e
// l
// l
// o
Working with Strings in Swift was changed several times during it's evolution and it doesn't look like C++ at all. You cannot subscript string to obtain individual characters, you should use index class for that. I recommend you read this article:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/StringsAndCharacters.html
As already pointed out in the other answers, the compiler error
is caused by the problem that you cannot index a Swift String with
integers.
Another problem in your code is that you have a nested loop which is
probably not intended.
Actually I would try to avoid string indexing at all and only
enumerate the characters, if possible. In your case, you can
easily keep track of the preceding character in a separate variable:
var lastChar: Character = " " // Anything except ":"
for char in line.characters {
if char == "(" {
maxOpen += 1;
if lastChar != ":" {
minOpen += 1;
}
}
// ...
lastChar = char
}
Or, since you only need to know if the preceding character is
a colon:
var lastIsColon = false
for char in string.characters {
if char == "(" {
maxOpen += 1;
if !lastIsColon {
minOpen += 1;
}
}
// ...
lastIsColon = char == ":"
}
Another possible approach is to iterate over the string and a shifted
view of the string in parallel:
for (lastChar, char) in zip([" ".characters, line.characters].joined(), line.characters) {
// ...
}
As others have already explained, trying to index into Swift strings is a pain.
As a minimal change to your code, I would recommend that you just create an array of the characters in your line up front:
let linechars = Array(line.characters)
And then anywhere you need to index into the line, use linechars:
This:
if i == 0 || line[i-1] != ":" {
becomes:
if i == 0 || linechars[i-1] != ":" {

Defaults too complex to compile with basic '+' operator

func updateTotalScore() -> Int {
var totalScoreDefault = NSUserDefaults.standardUserDefaults()
var highScoreAB1 = defaults.integerForKey("highScoreAB1")
var highScoreAB2 = defaults.integerForKey("highScoreAB2")
var highScoreAB3 = defaults.integerForKey("highScoreAB3")
var highScoreAB4 = defaults.integerForKey("highScoreAB4")
var highScoreAB5 = defaults.integerForKey("HighScoreAB5")
var highScoreAB6 = defaults.integerForKey("highScoreAB6")
var highScoreAB7 = defaults.integerForKey("highScoreAB7")
totalScoreDefault =
(defaults.integerForKey("highScoreAB1") + defaults.integerForKey("highScoreAB2")) + (defaults.integerForKey("highScoreAB3") + defaults.integerForKey("highScoreAB4")) + (defaults.integerForKey("highScoreAB5") + defaults.integerForKey("highScoreAB6")) + defaults.integerForKey("highScoreAB7") }
Adding multiple keys to get a total score default throws the following error. I tried grouping them together into pairs, and that did not work. Thank you in advance. This is a continuation from a post from yesterday.
Just as an addition to Logan's answer, because you are saying that you have problems with "complex expression" compiler error. This should compile:
func updateTotalScore() -> Int {
let defaults = NSUserDefaults.standardUserDefaults()
let totalScoretDefault =
defaults.integerForKey("highScoreAB1") +
defaults.integerForKey("highScoreAB2") +
defaults.integerForKey("highScoreAB3") +
defaults.integerForKey("highScoreAB4") +
defaults.integerForKey("highScoreAB5") +
defaults.integerForKey("highScoreAB6") +
defaults.integerForKey("highScoreAB7")
return totalScoretDefault
}
It looks like you are trying to add all of the highscores up into one UserDefault named totalScoreDefault. If so, you need to be setting the totalScoreDefault like so:
default.setInteger(highScoreAB1 + ... + highScoreAB7, forKey: "totalScoreDefault")
// You can also consider adding all highScores up before
// this to make the setInteger portion look cleaner.
var totalScore = 0
for var i = 1; i < 8; i++ {
totalScore += defaults.integerForKey("highScoreAB\(i)")
}
defaults.setInteger(totalScore, forKey: "totalScoreDefault")

Swift. For loop iteration.

Using the following:
func isosceles(triangleSides: Int)
{
var y = 0
for _ in 1...triangleSides {
y = y + 1
var stringBuilder = String()
for _ in 1...y
{
stringBuilder += "*"
}
println(stringBuilder)
}
}
isosceles(3)
I can make the following pattern:
*
**
***
I'm trying to write a function that outputs a sideways triangle of height 2n-1 and width n, so the output for n = 4 would be:
*
**
***
**
*
func triangle(triangleSides: Int)
{
var y = 0
var x = 0
var index: Int
for _ in 1...triangleSides {
y = y + 1
var stringBuilder = String()
for _ in 1...y
{
stringBuilder += "*"
}
println(stringBuilder + "\n")
}
for _ in 1..<triangleSides{
x = triangleSides - 1
var index: Int
var stringBuilder = String()
for index in stride(from: triangleSides - 1, through: 1, by: -1) {
stringBuilder += "*"
}
println(stringBuilder + "\n")
}
}
I get
*
**
***
**
**
Obviously it's going to be me thats the problem with the way I am trying to do this. If somebody could point me in the right direction that would be appreciated.
Thanks
Well, there are quite a few things you're doing that you don't really need to do... but, your main problem is that your 3rd and 4th for loops are wrong.
The way it is now, it's looping from 1 to triangleSides - 1 in the outer loop and triangleSize - 1 to 1 in the inner loop. Since you're not using the actual index of the for loop, that just makes both the outer and inner loops run triangleSides - 1 times.
What you want to do is loop from triangleSize - 1 to 1 in your outer loop and 1 to the current value of your outer loop in your inner loop. It'll make it easier if you let the for loop do its job and assign x directly instead of ignoring the loop's index with _ and manually calculating x.
Those changes would look like this (just the second set of for loops):
for x in stride(from: triangleSides - 1, through: 1, by: -1) {
var stringBuilder = String()
for _ in 1...x {
stringBuilder += "*"
}
println(stringBuilder + "\n")
}
If you want to clean it up a little more, you can also let the for loop do its job in the first set of loops and get rid of the declarations of x, y, and index at the start of your function:
func triangle(triangleSides: Int)
{
for y in 1...triangleSides {
var stringBuilder = String()
for _ in 1...y
{
stringBuilder += "*"
}
println(stringBuilder + "\n")
}
for x in stride(from: triangleSides - 1, through: 1, by: -1) {
var stringBuilder = String()
for _ in 1...x {
stringBuilder += "*"
}
println(stringBuilder + "\n")
}
}
Now, this:
triangle(3)
Outputs:
*
**
***
**
*
Here is my version:
func triangle(triangleSides: Int)
{
var y = 0
var x = 0
var index: Int
var stringBuilder = ""
for _ in 1...triangleSides {
stringBuilder += "*"
println(stringBuilder)
}
for z in reverse(1..<triangleSides) {
let index = advance(stringBuilder.endIndex, -1)
stringBuilder = stringBuilder.substringToIndex(index)
println(stringBuilder)
}
}
triangle(4)
Output:
*
**
***
****
***
**
*
Comments. I think the double loop was too complex.