Auxiliary function Grade calculator - f#

Why am I being told the let is unfinished?
let comp_grade (perc_exam, perc_homework, perc_attendance) = let (grade_exam, grade_homework, grade_attendance) =
(float)(perc_exam / 100 * grade_exam + perc_homework / 100 * grade_homework + perc_attendance / 100 * grade_attendance);
let COP4555_grade_computer = comp_grade(50,30,20);
let CEN3723_grade_computer = comp_grade(70,30,0);
let COP4555_student1_grade = COP4555_grade_computer (90, 95, 100);
let COP4555_student2_grade = COP4555_grade_computer (70, 80, 100);
let CEN3723_student1_grade = COP4555_grade_computer (90, 95, 100);
let CEN3723_student2_grade = COP4555_grade_computer (70, 80, 100);
Edit: Individually they work, but when I put them together the inner function now says it is unfinished.

let comp_grade ( perc_exam, perc_homework, perc_attendance)
(grade_exam, grade_homework, grade_attendance) =
float (perc_exam / 100 * grade_exam +
perc_homework / 100 * grade_homework +
perc_attendance / 100 * grade_attendance)
Return an function
let comp_grade ( perc_exam, perc_homework, perc_attendance) =
fun (grade_exam, grade_homework, grade_attendance) ->
float (perc_exam / 100 * grade_exam +
perc_homework / 100 * grade_homework +
perc_attendance / 100 * grade_attendance)

Related

Draw two or more markers at same time (library Charts)

How can I display two or more markers on a graph at the same time?
This is part of my code for this task
chartView.data = LineChartData(dataSets: [dataSet, dataSetForecast, dataSetUpper, dataSetLower])
let upperHigh = Highlight(x: (dataSetUpper.xMax + dataSetUpper.xMin) / 2,
y: dataSetUpper.yMax, dataSetIndex: 2)
upperHigh.dataIndex = 2
let lowerHigh = Highlight(x: (dataSetLower.xMax + dataSetLower.xMin) / 2,
y: dataSetLower.yMax, dataSetIndex: 3)
lowerHigh.dataIndex = 3
let forecastHigh = Highlight(x: (dataSetForecast.xMax + dataSetForecast.xMin) / 2,
y: dataSetForecast.yMax, dataSetIndex: 1)
forecastHigh.dataIndex = 1
chartView.highlightValues([upperHigh, lowerHigh, forecastHigh])
chartView.drawMarkers = true
chartView.data?.highlightEnabled = true
chartView.notifyDataSetChanged()
chartView.setVisibleXRangeMaximum(3600 * 3)
chartView.setVisibleXRangeMinimum(0)
Library https://github.com/danielgindi/Charts

Swift The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions

Following is method from a library in my project
public convenience init(hueRotate: Double) {
let c = cos(hueRotate)
let s = sin(hueRotate)
let m1 = [0.213, 0.715, 0.072,
0.213, 0.715, 0.072,
0.213, 0.715, 0.072]
let m2 = [0.787, -0.715, -0.072,
-0.213, 0.285, -0.072,
-0.213, -0.715, 0.928]
let m3 = [-0.213, -0.715, 0.928,
0.143, 0.140, -0.283,
-0.787, 0.715, 0.072]
let a = { i in
m1[i] + c * m2[i] + s * m3[i]
}
self.init(values: [a(0), a(1), a(2), 0, 0,
a(3), a(4), a(5), 0, 0,
a(6), a(7), a(8), 0, 0,
0, 0, 0, 1, 0])
}
on this following part of code I am getting compiler error saying The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
let a = { i in
m1[i] + c * m2[i] + s * m3[i]
}
How to fix this?
It should be enough to tell the compiler what a returns so change the declaration to
let a = { (i) -> Double in
m1[i] + c * m2[i] + s * m3[i]
}
Swift is having a problem with your equation being too long in the closure of var a. Try splitting the expression into smaller ones, like this:
let a = { i in
c * m2[i]
}
let b = { i in
s * m3[i]
}
let c = { i in
m1[i]
}
self.init(values: [a(0) + b(0) + c(0),
a(1) + b(1) + c(1),
a(2) + b(2) + c(2),
0, 0,
a(3) + b(3) + c(3),
a(4) + b(4) + c(4),
a(5) + b(5) + c(5),
0, 0,
a(6) + b(6) + c(6),
a(7) + b(7) + c(7),
a(8) + b(8) + c(8),
0, 0, 0, 0, 0, 1, 0])

iOS Swift3 - Convert coordinate

I'm trying to create annotations on the MapKit from a geoJSON file, but the problem is that the coordinates provided by the geoJSON file don't match the coordinate system that MapKit uses.
Question : How do I convert read the geoJSON file and convert the coordinates from `` to WGS84S?
Here is an example of what the geoJSON file looks like:
{"name":"MAPADDRESSPOINT","type":"FeatureCollection"
,"crs":{"type":"name","properties":{"name":"EPSG:3008"}}
,"features":[
{"type":"Feature","geometry":{
"type":"Point","coordinates": [97973.4655999987,6219081.53249992,0]},
"properties":{
"ADDRESSAREA_resolved":"Sadelvägen",
"multi_reader_id":1,
"multi_reader_full_id":1,
"BALSTATUS_resolved":"Gällande",
"REMARKTYPE_resolved":"",
"FARMADDRESSAREA_resolved":"",
"geodb_type":"geodb_point",
"multi_reader_keyword":"GEODATABASE_SDE_2",
"DEVIATEFROMSTANDARD_resolved":"",
"geodb_feature_is_simple":"yes",
"STATUS_resolved":"Ingen information",
"ADDRESSEDCONSTRUCTIONTYPE_resolved":"",
"SUPPLIER_resolved":"",
"multi_reader_type":"GEODATABASE_SDE",
"geodb_oid":18396,
"STAIRCASEIDENTIFIER_resolved":"",
"LOCATIONADDRESSSTATUS_resolved":"Gällande",
"POSITIONKIND_resolved":"Byggnad",
"BALADDRESSTYPE_resolved":"Gatuadressplats",
"COMMENTARY":"","
DTYPE":"",
"EXTERNALID":2,"GID":"{DEEA1685-2FF3-4BEB-823D-B9FA51E09F71}",
"MODIFICATIONDATE":"20170301173751",
"MODIFICATIONSIGN":"BAL service",
"OBJECTID":18396,
"REGDATE":"20110321151134",
"REGSIGN":"BAL service",
"STATUS":0,
"ADDRESSEDCONSTRUCTIONVALUE":"",
"LABELROTATIONANGLE":0,
"POSTCODE":"25483",
"POSITIONKIND":1,
"REALPROPERTYKEY":"120320803",
"BALSTATUS":2,
"BALADDRESSTYPE":1,
"BALID":"D5650F0B-EE54-4C4C-9C40-A8162118288C",
"DESIGNATIONVALUE":"",
"SYNCDATE":"20170301173751",
"STREETNAME":"Sadelvägen",
"ADDRESSAREA":554,
"YARDSNAME":"",
"PLACENAMEID":"",
"ADDRESSLABEL":"Sadelvägen 6",
"DESIGNATIONNUMBERLETTER":"",
"LOCATIONADDRESSSTATUS":3,
"CITY":"Helsingborg",
"ENUMERATOR":"6",
"SYMBOLROTATIONANGLE":0,
"POPULARNAME":"",
"geodb_feature_dataset":"Adress"
}
}
}]
}
https://en.m.wikipedia.org/wiki/Transverse_Mercator_projection
Longitude of natural origin 0° 00' 00.000" N
13° 30' 00.000" E
Scale factor at natural origin
1
False easting
150000
meters
False northing
0
FINAL (Playground) version
//: [Previous](#previous)
import Foundation
extension Double {
var rad: Double {
get {
return .pi * self / 180.0
}
}
var deg: Double {
get {
return 180.0 * self / .pi
}
}
}
// SWEREF99 13 30 (GRS80)
let φ0 = 0.0
let λ0 = 13.5.rad
let N0 = 0.0
let E0 = 150000.0
let k0 = 1.0
// GRS80
let a = k0 * 6378137.0
let b = k0 * 6356752.31414034
let n = (a - b)/(a + b)
let n2 = n * n
let n3 = n2 * n
let n4 = n3 * n
let a2 = a * a
let b2 = b * b
let e2 = (a2 - b2)/a2
let H0 = 1.0 + 1.0/4.0*n2 + 1.0/64.0*n4
let H2 = -3.0/2.0*n + 3.0/16.0*n3
let H4 = 15.0/16.0*n2 - 15.0/64.0*n4
let H6 = -35.0/48.0*n3
let H8 = 315.0/512.0*n4
let ν:(Double)->Double = { φ in
return a/(sqrt(1.0 - e2 * sin(φ) * sin(φ)))
}
let ρ:(Double)->Double = { φ in
return ν(φ) * (1.0 - e2) / (1.0 - e2 * sin(φ) * sin(φ))
}
let η2:(Double)->Double = { φ in
return ν(φ) / ρ(φ) - 1.0
}
var arcMeridian1:(Double)->Double = { φ in
let m = (a + b) / 2 * (H0 * φ + H2 * sin(2.0 * φ) + H4 * sin(4.0 * φ) + H6 * sin(6.0 * φ) + H8 * sin(8.0 * φ))
return m
}
var arcMeridian:(Double, Double)->Double = { φ1, φ2 in
return arcMeridian1(φ2) - arcMeridian1(φ1)
}
var cartografic:(Double,Double)->(Double,Double) = { φ, λ in
let νφ = ν(φ)
let ρφ = ρ(φ)
let η2φ = νφ / ρφ - 1.0
let s1 = sin(φ)
let s2 = s1 * s1
let c1 = cos(φ)
let c2 = c1 * c1
let c3 = c2 * c1
let c5 = c3 * c2
let t2 = s2/c2
let t4 = t2 * t2
let k1 = νφ * c1
let k2 = νφ/2.0 * s1 * c1
let k3 = νφ/6.0 * c3 * (νφ / ρφ - t2)
let k4 = νφ/24.0 * s1 * c3 * (5.0 - t2 + 9.0 * η2φ)
let k5 = νφ/120.0 * c5 * (5.0 - 18.0 * t2 + t4 + 14.0 * η2φ - 58.0 * t2 * η2φ)
let k6 = νφ/720.0 * s1 * c5 * (61.0 - 58.0 * t2 + t4)
let Δλ = λ - λ0
let Δλ2 = Δλ * Δλ
let Δλ3 = Δλ2 * Δλ
let Δλ4 = Δλ3 * Δλ
let Δλ5 = Δλ4 * Δλ
let Δλ6 = Δλ4 * Δλ
let N = arcMeridian(φ0,φ) + N0 + Δλ2 * k2 + Δλ4 * k4 + Δλ6 * k6
let E = E0 + Δλ * k1 + Δλ3 * k3 + Δλ5 * k5
return (N,E)
}
var geodetic:(Double,Double)->(Double,Double) = { N, E in
var φ = (N - N0) / a + φ0
var M = arcMeridian(φ0, φ)
var diff = 1.0
repeat {
φ += (N - N0 - M) / a
M = arcMeridian(φ0, φ)
diff = N - N0 - M
} while abs(diff) > 0.0000000001 // max 3 - 4 iterations
let E1 = E - E0
let E2 = E1 * E1
let E3 = E2 * E1
let E4 = E3 * E1
let E5 = E4 * E1
let E6 = E5 * E1
let E7 = E6 * E1
let νφ = ν(φ)
let νφ3 = νφ * νφ * νφ
let νφ5 = νφ3 * νφ * νφ
let νφ7 = νφ5 * νφ * νφ
let ρφ = ρ(φ)
let η2φ = νφ / ρφ - 1.0
let s1 = sin(φ)
let s2 = s1 * s1
let c1 = cos(φ)
let t1 = s1 / c1
let t2 = t1 * t1
let t4 = t2 * t2
let t6 = t4 * t2
let k1 = 1.0 / (c1 * νφ)
let k2 = t1 / (2.0 * ρφ * νφ)
let k3 = 1.0 / (6.0 * νφ3) * (νφ / ρφ + 2.0 * t2)
let k4 = (t1 / (24.0 * ρφ * νφ3)) * (5.0 + 3.0 * t2 + η2φ - 9.0 * t2 * η2φ)
let k5 = 1.0 / (120.0 * νφ5) * (5.0 + 28.0 * t2 + 24.0 * t4)
let k6 = (t1 / (720.0 * ρφ * νφ5)) * (61.0 + 90.0 * t2 + 45.0 * t4)
let k7 = (t1 / (5040.0 * ρφ * νφ7)) * (61.0 + 662.0 * t2 + 1320.0 * t4 + 720.0 * t6)
φ = φ - E2 * k2 + E4 * k4 - E6 * k6
let λ = λ0 + E1 * k1 - E3 * k3 + E5 * k5 - E7 * k7
return (φ, λ)
}
print("pecision check")
let carto0 = cartografic(55.0.rad, 12.75.rad)
print(carto0,"err:", carto0.0 - 6097487.637, carto0.1 - 102004.871)
let carto1 = cartografic(61.0.rad, 14.25.rad)
print(carto1,"err:", carto1.0 - 6765725.847, carto1.1 - 190579.995)
print()
print("given position: N 6219081.53249992, E 97973.4655999987")
let geo = geodetic(6219081.53249992, 97973.4655999987)
print("geodetic: φ =", geo.0.deg,"λ =", geo.1.deg)
//: [Next](#next)
prints
pecision check
(6097487.6372101102, 102004.87085248799) err: 0.00021011009812355 -0.000147512007970363
(6765725.8471242301, 190579.99493182387) err: 0.000124230049550533 -6.81761302985251e-05
given position: N 6219081.53249992, E 97973.4655999987
geodetic: φ = 56.0916410844269 λ = 12.6641326192406
position on map
I dont understand what are you looking for exactly but what I would do (since you are using swift) is create an extension of MKPointAnnotation and add a new initialiser that takes the geoJSON, parse it, fetch the coordinates (and whatever data you intend to put in the annotation object) and return a MKPointAnnotation with the required data.
just incase you dont know how to parse a JSON here s an example :
do {
let dictionary = try JSONSerialization.jsonObject(with: geoJSON!,
options: JSONSerialization.ReadingOptions.mutableContainers) as! [String: AnyObject]
let features = dictionary["features"] as! [[String:AnyObject]]
let geometry = features[0]["geometry"] as! [String: AnyObject]
....
}catch{
//incase the json doesnt get parsed
}
keep going until you reach the coordinates ..;
obviously dont use force cast incase you are hesitate about a value instead use guard or if let ....

Need to restart numbering when it gets to 1 and jump to 99

How would I go about doing this? the code I have is
let myInt = Int(currentSaleLabel.text!)
let sale1Number = (myInt! - 1 + 100) % 100
let sale2Number = (sale1Number - 1 + 100) % 100
let sale3Number = (sale2Number - 1 + 100) % 100
let sale4Number = (sale3Number - 1 + 100) % 100
let sale5Number = (sale4Number - 1 + 100) % 100
let sale6Number = (sale5Number - 1 + 100) % 100
let sale7Number = (sale6Number - 1 + 100) % 100
let sale8Number = (sale7Number - 1 + 100) % 100
let sale9Number = (sale8Number - 1 + 100) % 100
let sale10Number = (sale9Number - 1 + 100) % 100
This works fine for numbers 0-99 but I need to eliminate the number 0 also.
One approach is to make a limit of 99 with modulo % operator, like this:
let sale1Number = (myInt! - 1 + 100) % 100
This decrements myInt, and wraps it to 99 when it gets negative. Adding 100 prior to applying % has no effect on numbers in range 0..99. Negative numbers above -100 will get processed correctly.
I am actually also trying to avoid the number 0
You can use a modified formula, like this:
let sale1Number = (myInt! - 2 + 100) % 100 + 1

How can I change the Double value in my dictionary outside the function?

var grades: [String : Double]
grades = ["A": 0.0, "A-": 0.0, "B+": 0.0, "B": 0.0, "B-": 0.0, "C+": 0.0, "C": 0.0, "C-": 0.0, "D+": 0.0, "D": 0.0, "D-": 0.0, "F": 0.0]
func calcGPA() {
if let a = grades["A"], amin = grades["A-"], bplu = grades["B+"], b = grades["B"], bmin = grades["B-"], cplu = grades["C+"], c = grades["C"], cmin = grades["C-"], dplu = grades["D+"], d = grades["D"], dmin = grades["D-"], f = grades["F"] {
// Divide by this
let gradesAdded = a + amin + bplu + b + bmin + cplu + c + cmin + dplu + d + dmin + f
//grades multiplied by their values and added ex. a * 4.0 + amin * 3.7
let gradesCalculated = a * 4.0 + amin * 3.7 + bplu * 3.3 + b * 3.0 + bmin * 2.7 + cplu * 2.3 + c * 2.0 + cmin * 1.7 + dplu * 1.3 + d * 1.0 + dmin * 0.7 // Dont do F because it would just add 0
var gpa = gradesCalculated / gradesAdded
if gpa.isNaN {
gpa = 0.0
}
}
}
Is there a way to do something like grades["A"] += 1.0 so that it goes up by one and I can call calcGPA()? I can't figure out how to make this work. Any help on this would be awesome
You can increase a value in your dictionary by force unwrapping the lookup:
grades["A"]! += 1.0
but this is dangerous because it will crash if the key isn't in the dictionary. So, you should check:
if let count = grades["A"] {
grades["A"] = count + 1
}
Here is an updated version of your program:
func calcGPA(_ termGrades: [String]) -> Double? {
var grades: [String: Double] = ["A": 0.0, "A-": 0.0, "B+": 0.0, "B": 0.0, "B-": 0.0, "C+": 0.0, "C": 0.0, "C-": 0.0, "D+": 0.0, "D": 0.0, "D-": 0.0, "F": 0.0]
var gpa: Double?
for grade in termGrades {
if let count = grades[grade] {
grades[grade] = count + 1
} else {
print("Hmmm, \(grade) is not a valid value for a grade")
return nil
}
}
if let a = grades["A"], amin = grades["A-"], bplu = grades["B+"], b = grades["B"], bmin = grades["B-"], cplu = grades["C+"], c = grades["C"], cmin = grades["C-"], dplu = grades["D+"], d = grades["D"], dmin = grades["D-"], f = grades["F"] {
// Divide by this
let gradesAdded = a + amin + bplu + b + bmin + cplu + c + cmin + dplu + d + dmin + f
//grades multiplied by their values and added ex. a * 4.0 + amin * 3.7
let gradesCalculated = a * 4.0 + amin * 3.7 + bplu * 3.3 + b * 3.0 + bmin * 2.7 + cplu * 2.3 + c * 2.0 + cmin * 1.7 + dplu * 1.3 + d * 1.0 + dmin * 0.7 // Dont do F because it would just add 0
gpa = gradesAdded == 0 ? nil : gradesCalculated / gradesAdded
}
return gpa
}
// example calls
calcGPA(["E"]) // nil "Hmmm, E is not a valid value for a grade"
calcGPA(["A-"]) // 3.7
calcGPA(["A", "B"]) // 3.5
calcGPA(["B", "B+", "A-"]) // 3.333333333333333
calcGPA([]) // nil
Notes:
I changed your function to take an array of grades and return a Double? (Optional Double).
nil is returned if anything goes wrong (input array is empty, input array contains invalid grade such as "E").
Divide by zero is avoided ahead of time by checking the divisor before the calculation.
Alternate Solution:
And now for something completely different...
Inspired by #CodeBender's comment, here is an implementation that uses an enum with an associated value to represent the grades:
enum Grade: Double {
case A = 4.0
case Aminus = 3.7
case Bplus = 3.3
case B = 3.0
case Bminus = 2.7
case Cplus = 2.3
case C = 2.0
case Cminus = 1.7
case Dplus = 1.3
case D = 1.0
case Dminus = 0.7
case F = 0
}
func calcGPA(_ termGrades: [Grade]) -> Double? {
if termGrades.count == 0 {
return nil
} else {
let total = termGrades.reduce(0.0) { (total, grade) in total + grade.rawValue }
return total / Double(termGrades.count)
}
}
// example calls
calcGPA([.A, .B]) // 3.5
calcGPA([.B, .Bplus, .Aminus]) // 3.3333333333
calcGPA([.A, .A, .Bplus]) // 3.7666666666
calcGPA([.F, .F, .F]) // 0
calcGPA([]) // nil

Resources