diff --git a/2019/Julia/Code/1.HelloWorld.jl b/2019/Julia/Code/1.HelloWorld.jl deleted file mode 100644 index f6195a5..0000000 --- a/2019/Julia/Code/1.HelloWorld.jl +++ /dev/null @@ -1,7 +0,0 @@ -println("Hello Julia!") - -x = 3 -y = 2 -z = x + y - -println(z) diff --git a/2019/Julia/Code/10.structs1.jl b/2019/Julia/Code/10.structs1.jl deleted file mode 100644 index 330eee1..0000000 --- a/2019/Julia/Code/10.structs1.jl +++ /dev/null @@ -1,173 +0,0 @@ - -# User defined types are made with the struct keyword. Member variables are -# listed in the struct body as follows. -# Keep in mind that julia does not support redefining of types by default, -# so whenever you change anything in the struct (field names/types, etc.) -# you have to restart the REPL. -# Alternatively you could look into the package Revise.jl which solves -# some of these problems. -struct TestType - x - y - z -end - -# Every struct gets a default constructor that is the typename taking -# in all the member variables in order. -t = TestType(1, 2, 3) - -# Every struct also gets a default print function that shows the variable -# in style of the constructor. -@show t - -# Accessing the member variables of the struct is done simply by just -# writing variable_name.field_name -# every field is always public as julia does not implement any heavy -# object oriented design. -@show t.x - -# This line is illegal since struct are immutable by default. -# t.y = 5 - -# Field mutability can be achieved by adding the keyword "mutable" in front. -# However for simple structs, like this xyz-point like structure, it is -# much more efficient if you can avoid making it mutable. This has to do -# with how mutable struct are allocated differently then immutable ones. -# Read more in the "Types" section of the julia documentation. -mutable struct TestType2 - x::Float64 - y::Float64 - z::Float64 -end - -# Also as illustrated above, the fields in a struct can be strictly typed. -# This is usually a good idea since it makes the struct take a constant -# amount of space, and removes a lot of type bookkeping. - -t2 = TestType2(1.68, 3.14, 2.71) - -# With this mutable struct, the variable now behaves more like a general -# container (Array/vector) so you can change the fields. -t2.y = 1.23 -@show t2 - -# You can also make parametric types, kind of like templates in C++. -# This essentially creates a new type for each new T, so it alleviates the -# problem of keeping track of the types of the individual fields. -struct TestType3{T} - x::T - y::T - z::T -end - -# This now constructs a TestType3{Int64} -t3 = TestType3(1, 2, 3) -@show t3 - - -# This will be the example struct throughout the rest of the file. -struct Polar{T<:Real} - r::T - θ::T - - # You might want to make your own constructors for a type. - # These are typically made inside the struct body since this overrides - # the creation of the default constructor described above. - function Polar(r::T, θ::T) where T <: Real - # Doing some constructy stuff - println("Creating Polar number (r = $r, θ = $θ)") - - # The actual variable is created by calling the "new()" function - # which acts as the default constructor. This however is just - # accessible to functions defined inside the struct body. - new{T}(r, θ) - end - - # You might want to implement multiple different constructors. - # This one is short and simple so it can be created with the inline syntax. - # The zero(T) function finds the apropriate "zero" value - # for the given type T. That way no implicit conversions have to be done. - Polar{T}() where T <: Real = new{T}(zero(T), zero(T)) -end - -# Not all constructors have to be defined inside the struct body, but here -# outside the body we no longer have access to the "new()" function since -# the compiler doesn't have any way to infer which type "new" would refer -# to out here. So instead we have to use one of the constructors we defined -# inside the struct. -# This constructor is very similar to the Polar{T}() function but instead -# of writing p = Polar{Int}() to take the type in as a template argument -# you would pass the type in as an actual argument; p = Polar(Int) -Polar(::Type{T}) where T <: Real = Polar{T}() - - -# Constructing with the first constructor -p = Polar(3.14, 2.71) -@show p - -# Constructing with the empty constructor -p = Polar{Int}() -@show p - -# Constructing with the constructor taking the type as an argument -p = Polar(Float16) -@show p - - -# You might want to overload som basic operators and functions on your -# type. One common thing to want to override is how your variables are printed. -# Since there are so many different ways of converting a variable to text -# (print, println, @printf, string, @show, display, etc.) -# it can be difficult to find out which function is actually responsible -# for converting to text. -# This function turns out to be the Base.show() function. -# It takes in an IO stream object and and the variable you want to show. - -# Since the funtion is from the Base module -# we have to override Base.show specifically -# Also it is very important to actually specify the type of the variable here -# so that we are actually specifying the show function for our type only -# and not for any general type. -function Base.show(io::IO, p::Polar) - # Say we want to print our polar number as r * e^(i θ) style string - show(io, p.r) # non strings we want to recursively show - write(io, " ⋅ ℯ^(i ⋅ ") # strings we want to write directly with write - show(io, p.θ) - write(io, ")") -end - -# Now our polar numbers are printed as we specified -p = Polar(3.14, 2.71) -@show p -println(p) -display(p) - -# Even converting to a string is now done with our show functon -s = string(p) -@show s - - -# Overloading operators is even simpler as every infix operator is just a -# function; a + b is equivalent to +(a, b) (for all you lisp lovers) - -# For some reason we cannot write the Base.* inline for infix operators -import Base.* -*(p1::Polar{T}, p2::Polar{T}) where T = Polar(p1.r * p2.r, p1.θ + p2.θ) - -# Multiplication between different types might also be useful -*(x::T, p::Polar{T}) where T = Polar(x * p.r, p.θ) -# Implementing the reverse mulitplication such that it becomes commutative -*(p::Polar{T}, x::T) where T = x * p - -p1 = Polar(2.0, 15.0) -p2 = Polar(3.0, 30.0) -p3 = p1 * p2 -@show p3 - -# The in-place arithmetic operators (+=, -=, *=, /=, etc.) are not actual -# operators but rather just an alias for a = a * b so they need not be -# implemented seperately. If the memory copying is a problem and you -# really have to do it in-place the way to do that would be to make some -# sort of mult!(p, x) function. -p3 *= 0.5 -@show p3 diff --git a/2019/Julia/Code/11.structs2.jl b/2019/Julia/Code/11.structs2.jl deleted file mode 100644 index c93b4d0..0000000 --- a/2019/Julia/Code/11.structs2.jl +++ /dev/null @@ -1,27 +0,0 @@ - -# This is just a super simple example to illustrate the "call" operator. - -# Simple polynomial type. The Polynomials.jl package is basically a more -# complete version of this example. -struct Poly{T} - coeffs::Vector{T} -end - -# Could implement a whole bunch of operators (+, -, *, /, show, etc.) -# but that can be left as an exercise for the reader :3 -# Also the Polynomials.jl package have implemented most of those. - -# Here, the whole point of this example; This function basically makes -# the variable, p, act as a polynomial function on x. -function (p::Poly{T})(x::T) where T <: Number - ret = zero(T) - for i in 1 : length(p.coeffs) - ret += p.coeffs[i] * x^(i - 1) - end - ret -end - -# Now any variable of type Poly can be used as if it was a function -# This gives some really clean syntax :) -p = Poly([0.0, -3.0, 0.0, 1.0]) # p = 0 - 3 x + 0 x^2 + 1 x^3 -@show p(3.0) diff --git a/2019/Julia/Code/12.structs3.jl b/2019/Julia/Code/12.structs3.jl deleted file mode 100644 index 3cb823c..0000000 --- a/2019/Julia/Code/12.structs3.jl +++ /dev/null @@ -1,216 +0,0 @@ - -# This is a more complete example of a linked list implementation, but exists -# mainly to illustrate how to implement indexing and iteration. - -# okay, this is the dirtiest hack I have ever done in julia. -# Julia is really finicky when it comes to redefining structs. -# Usually it isn't a problem if you haven't changed anything, -# but because of the recursive inclusion in the Node_ struct it was really -# unhappy, so this basically runs this if block the first time -# and not any subsequent times. -if !isdefined(@__MODULE__, :__first__) -__first__ = true - -# The node struct that actually holds the values -mutable struct Node_{T} - data::T - prev::Union{Node_{T}, Nothing} - next::Union{Node_{T}, Nothing} -end - -# An alias for a type union such that we can set a node to the value nothing -# when we want to indicate the end of the list. -const Node{T} = Union{Node_{T}, Nothing} - -# Since we made the alias for Node, we make this wrapper for the constructor -# of the actual Node_ object. There are probably better ways to do this -# but this works fine. -function make_node(data::T, prev::Node{T}, next::Node{T}) where T - Node_{T}(data, prev, next) -end - -# The wrapper struct for the nodes. Most of the methods will be implemented -# on this type. -# It is also specified as a subtype of the abstract type AbstractArray. -# This signalises that it will mostly act like an array -# and makes it possible to pass a LinkedList into a function that is specified -# to take in objects of type AbstractArray. This gives a bunch of functions -# that needs to be implemented, and some that can be overridden. All of these -# are listed under the "Intefaces" section in the julia docs. -# Here we will implement the required methods and the methods for iteration. -mutable struct LinkedList{T} <: AbstractArray{T, 1} - head::Node{T} - tail::Node{T} - items::Int # Keeping track of how many items for quick length checking - - # Implementing a default constructor - LinkedList{T}() where T = new{T}(nothing, nothing, 0) -end - -end # End of the dirty hack - -# Constructor to create a list from a collection of elements -function LinkedList(elems::AbstractArray{T}) where T - l = LinkedList{T}() - for e in elems - push!(l, e) - end - l -end - - -# Not required for AbstractArray, but makes sence to implement -function Base.push!(l::LinkedList{T}, v::T) where T - n_node = make_node(v, nothing, nothing) - - if l.head === nothing - l.tail = l.head = n_node - else - l.tail.next = n_node - n_node.prev = l.tail - l.tail = n_node - # n_node.next = l.head # Uncomment this one if you feel brave ;) - end - l.items += 1 - l -end - -# One of the reqired functions for AbstractArray. size returns a tuple -# of all the dimensions, but this is a 1d collection so it only contains -# one element. -Base.size(l::LinkedList) = (l.items, ) - -# Implements the iteration function. This makes it possible to for example -# write something like "for element in list" to iterate through the list. -# The function returns a 2-tuple where the first element is the next iteration -# item and the second element is the next state. The state is some variable -# that determines the next element and state. When the function returns -# nothing, the loop is done. -function Base.iterate(l::LinkedList, state=l.head) - if state === nothing - nothing # If the state is nothing, we return nothing - else - (state.data, state.next) # Else the next item/state is returned - end -end - -# Implements a simple show function for nicer printing. The default show -# function is ridiculous when you have circular/recursive containment in -# your structs, so it is necessary to implement a nicer version. -function Base.show(io::IO, l::LinkedList{T}) where T - show(io, l.items) - write(io, "-element LinkedList{") - show(io, T) - write(io, "}:\n ") - first = true - for elem in l - if !first - write(io, " → ") - end - first = false - show(io, elem) - end -end - -# A utility function for both the getindex and setindex! functions -function findnode(l::LinkedList, i::Int) - if !(1 <= i <= length(l)) - throw(BoundsError(l, i)) # Throwing an error if out of bounds - end - curnode = l.head - for j in 1 : i - 1 - curnode = curnode.next - end - curnode -end - -# Another required function for AbstractArray. -# This function makes it possible to read the element at a certain index -# with the syntax l[i] -Base.getindex(l::LinkedList, i::Int) = findnode(l, i).data - -# The complimentary function for seting elements at a given index -# with corresponding syntax l[i] = v -Base.setindex!(l::LinkedList{T}, v::T, i::Int) where T = findnode(l, i).data = v - - -# Practial to override the copy function. In this case it it really -# simple to set up because of the way we made the constructor. -Base.copy(l::LinkedList) = LinkedList(l) - -# Implementing the append function as well. Not necessary but practical to have. -function Base.append!(l::LinkedList{T}, l2::AbstractArray{T}) where T - for elem in l2 - push!(l, elem) - end -end - -# Implementing insert! for a linked list is quite useful -function Base.insert!(l::LinkedList{T}, i::Int, v::T) where T - node = findnode(l, i) - n_node = make_node(v, node, node.next) - if node.next !== nothing - node.next.prev = n_node - end - node.next = n_node - l -end - -# Same goes for deleteat! -function Base.deleteat!(l::LinkedList, i::Int) - node = findnode(l, i) - if node.prev !== nothing - node.prev.next = node.next - end - if node.next !== nothing - node.next.prev = node.prev - end - l -end - -# It can be useful to reverse a list -function Base.reverse!(l::LinkedList) - cur_node = l.head - for i = 1 : length(l) - cur_node.prev, cur_node.next = cur_node.next, cur_node.prev - cur_node = cur_node.prev - end - l.head, l.tail = l.tail, l.head - l -end - -# It can also be useful to make a reversed copy of a list -Base.reverse(l::LinkedList) = reverse!(copy(l)) - - -# Some test code: - -# Creating a linked list -l = LinkedList(1 : 5) -@show l - -# showing the third element -@show l[3] - -# setting the third element -l[3] = 7 -@show l - -# inserting the value 8 between 2nd and 3rd node -insert!(l, 2, 8) -@show l - -# deleting the second node -deleteat!(l, 2) -@show l - -# since all required functions for AbstractArray have been implemented -# standard functions, such as sort!, should now work. However if performance -# is important you should probably implement your own version of functions -# so that it is done more efficiently for the collection in question. -# for example the sort function here will do a lot of index operations -# and since finding a node in a linked list is O(n) complexity and -# sort! is O(n log n) list operations, the whole runtime becomes O(n^2 log n). -sort!(l) -@show l - diff --git a/2019/Julia/Code/13.fileIO.jl b/2019/Julia/Code/13.fileIO.jl deleted file mode 100644 index ed09858..0000000 --- a/2019/Julia/Code/13.fileIO.jl +++ /dev/null @@ -1,39 +0,0 @@ - -# File IO is really similar to how it would be done in python and C. - -io = open("test.txt", "w") # Opens test.txt for writing -write(io, "Hello World!") # writes a string to it -close(io) # closes the file - -# However the more appropriate way to do it would be more similar to -# Python's "with" statement. This encloses the file handling in a code block -# and automatically closes the filestream and does cleanup if anything goes -# wrong. -open("test.txt", "w") do io - write(io, "Hello\nWorld!") -end - -# The do-syntax here is really just syntactical sugar for giving the -# open() function a function as an argument - -# The following syntax is effectively what the do-syntax above does. -# Create a function taking in a single argument with the file-handling code -function f(io) - write(io, "Hello\nWorld!") -end - -# call the open function with this function as the first parameter -open(f, "test.txt", "w") - -# This makes for some really clean and safe file handling syntax. -s = open("test.txt", "r") do io - collect(eachline(io)) -end -display(s) - -# for simple functions as the one above it is possible to just pass -# the the function directly in without using the do-syntax -# for a really compact one line function call -# The ∘ symbol is function composition (from mathematics) -s = open(collect ∘ eachline, "test.txt", "r") -display(s) diff --git a/2019/Julia/Code/14.IOBuffer.jl b/2019/Julia/Code/14.IOBuffer.jl deleted file mode 100644 index a0048ee..0000000 --- a/2019/Julia/Code/14.IOBuffer.jl +++ /dev/null @@ -1,15 +0,0 @@ - -# IOBuffers are like writing to a file in memory. They are really efficient -# when creating strings and work like any other IO object we've worked with. -io = IOBuffer() - -a = 42 -write(io, "i = ") -print(io, a) - -# To retrieve the written data from the buffer we call take!(). This returns -# a Vector{UInt8} so to interpret it as a string we call String() -s = String(take!(io)) - -println(s) - diff --git a/2019/Julia/Code/15.lambdas.jl b/2019/Julia/Code/15.lambdas.jl deleted file mode 100644 index daba918..0000000 --- a/2019/Julia/Code/15.lambdas.jl +++ /dev/null @@ -1,35 +0,0 @@ - -# A lambda function is made with an arrow from the arguments -# to the function body -f = x -> 2x^2 -@show f(2) - -# If the function takes more then one argument, parenthesis are required -g = (x, y) -> x * y -@show g(2, 3) - -# This also holds for functions taking no arguments -p = () -> Float64(π) -@show p() - -# Function currying is possible, so if anyone wants to do lambda calculus -# feel free. -h = x -> y -> x / y -@show h(12)(4) - -# If a function has to be written over multiple lines, this can be done -# with a "begin" block. -fib = n -> begin - a, b = 0, 1 - for i in 1 : n - a, b = b, a + b - end - a -end -@show fib.(0:6) - -# Lambdas can be useful when passing a function as an argument -# without wanting to give it a name. Here is an example using a lambda -# instead of using the do-syntax for file handling -s = open(io -> String(read(io)), "test.txt", "r") -println(s) diff --git a/2019/Julia/Code/16.Macro.jl b/2019/Julia/Code/16.Macro.jl deleted file mode 100644 index 7ee313b..0000000 --- a/2019/Julia/Code/16.Macro.jl +++ /dev/null @@ -1,28 +0,0 @@ - -# Julia comes with a lot of useful macros. Youv'e already seen the @show macro. -x = 5 -@show x - -# Macros are a small part of julias huge metaprogramming system. -# There exists a bunch of useful macros, both in julia itself, and in -# different packages. A macro is basically a function that takes in a list -# of arguments and generates a code block at compiletime. It is possible -# to create your own macros, but that takes some reading up on the -# metaprogramming section in the julia docs. - - -# Probably one of my most used macros is the @time macro -reallyslowfunction() = sleep(2) -@time reallyslowfunction() - -# If you want to time a whole code block this is done with a "begin" block -@time begin - # Slow code - sleep(1) -end - -# The @inbounds macro removes all checks to see if you try to acces elements -# outside any container, so might be faster, but definately more unsafe. -a = [1, 2, 3] -@inbounds println(a[2]) - diff --git a/2019/Julia/Code/17.Broadcast.jl b/2019/Julia/Code/17.Broadcast.jl deleted file mode 100644 index 3fdeb5a..0000000 --- a/2019/Julia/Code/17.Broadcast.jl +++ /dev/null @@ -1,21 +0,0 @@ - -# The broadcast operator (.) can be quite useful when dealing with arrays. -# Basically whenever an operator or function is used, you can just write -# a dot (.) before the operator/function to make it act elementwise. - -# Here we elementwise add 3 to the array -a = [1, 2, 3, 4] -a .+= 3 -@show a - -# Here we elementwise multiply a by 2 and then elementwise add a and b. -b = a .* 2 -@show b -c = a .+ b -@show c - -# To elementwise use more general functions the dot symbol is placed between -# the function name and parentheses. -f(x) = 2x^2 -d = f.(c) -@show d diff --git a/2019/Julia/Code/18.Unicode.jl b/2019/Julia/Code/18.Unicode.jl deleted file mode 100644 index cbc293f..0000000 --- a/2019/Julia/Code/18.Unicode.jl +++ /dev/null @@ -1,42 +0,0 @@ - -# Julia uses unicode characters quite heavily. Mostly it is possible to avoid -# using unicode completely, but it can make code look quite clean. -# The unicode autocompletion for vscode mostly works, but can be a bit -# unreliable, but the julia REPL (console) is also useful for writing unicode. -# There is a whole section in the Julia docs dedicated to how to input different -# unicode characters, so just search "Unicode Input" in the docs. - -# We've seen a lot of different unicode symbols, here are some more useful ones. - -# The infix operator for boolean xor is the ⊻ (\veebar, \xor) symbol. -b = true ⊻ false - -# In the LinearAlgebra package the ⋅ (\cdot) symbol is overloaded as the -# scalar product of vectors. -using LinearAlgebra -a = [1, 2] ⋅ [2, 1] -@show a - -# Where you would write "in" you could probably use either ∈ (\n) or ∉ (\notin) - -# You can use ∈ for iteration -for i ∈ 1 : 5 - # dostuff -end - -# It can also be used for checking if an element is in a collection -3 ∈ [1, 2, 3, 4] -# And the notin symbol can be used to check if something isn't in the collection -2 ∉ [1, 2, 3, 4] - -# The mathematical constants π (\pi) and ℯ (\euler) are defined as irrationals -# that can be cast to a numeric type and they will be calculated to the -# required precision. - -# This calculates pi the the precision of a Float64 -p = Float64(π) -@show p - -# This will calculate the fraction closest to ℯ using Int16. -e = Rational{Int16}(ℯ) -@show e diff --git a/2019/Julia/Code/19.Packages.txt b/2019/Julia/Code/19.Packages.txt deleted file mode 100644 index 721cb48..0000000 --- a/2019/Julia/Code/19.Packages.txt +++ /dev/null @@ -1,49 +0,0 @@ - -Therer are a lot of different useful packages for julia. All official -Packages can be found at https://juliaobserver.com/packages (I think) - -Here are a couple of good packages i use a lot. - -IJulia: -This package is required for using Julia in jupyter. - -LinearAlgebra: -This package comes with julia without any need for installation and includes -a lot of linear algebra functionality, comparable to numpy.linalg. - -Statistics: -Distributions, mean, standard deviations, etc... - -Plots: -Creates nice plots. Has support for multiple backends (including pyplot). - -PyCall: -makes it possible to import python packages into julia and write python code -in julia files. Anytime there exists a useful python package and no julia -equivalent, this package saves lives. - -Primes: -I do not know what magic they put into making this package, but I have never -seen a so fast funtion for checking if a number is prime ever. -The package is useful for working with prime numbers. - -Memoize: -A useful package for automatically memoizing a function. For people taking -algorithms and datastructures, this will make more sence later in the course. - -Images: -Useful to handle images. Terrible slow to load the package, but once loaded -it is quite fast and very featureful. - -SymPy: -A wrapper for pythons sympy package which is arguably much better than -sympy itself. - -Printf: -Wrapper for the C- printf style functions for fast string formating. - -CSV: -Package for reading/writing .csv (comma seperated values) files. - -JSON: -Package for reading/writing .json files. diff --git a/2019/Julia/Code/2.functions.jl b/2019/Julia/Code/2.functions.jl deleted file mode 100644 index 0782592..0000000 --- a/2019/Julia/Code/2.functions.jl +++ /dev/null @@ -1,31 +0,0 @@ - -# Standard function definition -function f(x, y) - return x + y -end - -# Function implicitly returns the value of the last line -# of the function so no return keyword is required -function g(x, y) - x - y -end - -# Functions can be defined one one line like this. -# This is just a shorthand and is compiled identically to the ones above -h(x, y) = x * y - - -# Can enforce types on function arguments and return value -# This makes it possible to create multiple functions -# with the same name but different types; These are called methods -f(x::Float64, y::Float64)::Float64 = x / y - - -# Runs the generic method of the function at the top of the file -println(f(2, 3)) - -# Runs the specific method defined for two Float64. -println(f(2.2, 3.2)) - -# Also falls back the the generic method as input is (::Float64, ::Int64) -println(f(1.6, 3)) diff --git a/2019/Julia/Code/3.arithmetic.jl b/2019/Julia/Code/3.arithmetic.jl deleted file mode 100644 index debfa37..0000000 --- a/2019/Julia/Code/3.arithmetic.jl +++ /dev/null @@ -1,41 +0,0 @@ - - -# Also possible to enforce types on local variables - -function main() - # Int is an alias for Int32 or Int64 depending on your installation - # 32 bit vs 64 bit - a::Int = 14 - b::Int = 7 - - # Enforces the type of c for the rest of the scope - c::Int = a + b - @show typeof(c) c # The @show macro is basically a debug print - - # Normal division of integers returns Float64 - # Assignment to c tries to convert result to the - # type of c as the type is enforced. - # If unable to convert to Int it throws an appropriate exception - c = a / b - @show typeof(c) c - - # // is rational division. This returns a rational number - c = a // b - @show typeof(c) c - - - # Integer division is done by div, fld or cld (floor divide/ceil divide) - # div rounds towards zero (1.5 -> 1, -2.7 -> -2) - # floor rounds downwards (1.5 -> 1, -2.7 -> -3) - # ceil rounds upwards (1.5 -> 2, -2.7 -> -2) - c = div(a, b) - c = fld(a, b) - c = cld(a, b) - - # Exponentiation is done with the ^ symbol as in most calculator programs - c = a^b - @show c -end - -main() - diff --git a/2019/Julia/Code/4.strings.jl b/2019/Julia/Code/4.strings.jl deleted file mode 100644 index e5aa626..0000000 --- a/2019/Julia/Code/4.strings.jl +++ /dev/null @@ -1,84 +0,0 @@ - -# Strings are made with double quotes "" -# Single quotes '' are reserved for single characters (i.e. c/c++) -s = "Hello world" -println(s) - - -# When converting to a string the function string (with lower case s) -# is used. -a = 3.14 -s = string(a) - -println(s) # Prints 3.14 - - -# The length of a string can be found with the length function -# similar to len in python - -@show length(s) - - -# The function String (with upper case S) is used for more direct -# interpretation of data as a string - -a = UInt8[65, 66, 67] # ASCII codes for "ABC" - -println(String(a)) # Prints ABC -println(string(a)) # Prints UInt8[0x41, 0x42, 0x43] - - -# When converting from string to some numeric value, the parse function -# is used. This function takes in the type to try to parse to as well -# as the string to parse. -s = "128" -a = parse(Int, s) - -@show a - -s = "3.14" -a = parse(Float64, s) - -@show a - - -# Easy inline string formating can be done with the $ (eval) symbol -a, b = 3, 5 - -s = "a, b = $a, $b" # generates string "a, b = 3, 5" -println(s) - -s = "a + b = $(a + b)" # "a + b = 8" -println(s) - -# However it is usually faster (performance wise) to just pass in -# multiple arguments to f.exs. println -println("a + b = ", a + b) - - -# The "raw" string macro is very useful when copying raw text and not -# wanting to worry about special characters doing special stuff -# (i.e. \n for new line). A common use for this is filepaths - -filepath = raw"C:\Users\somefolder\somefile.txt" -@show filepath - -# String concatenation is, somewhat weirdly, done with the * sign -# instead of the + sign. Julia's justification for this is that -# addition (+) is reserved for commutative operations (a + b = b + a) -# and since string concatenation is not commutative it gets the multiplication -# symbol instead. -s = "foo" * "bar" -println(s) - -# This by extension means that if you want to repeat a string n times -# this is done with the exponentiation (^) sign -s = "foo"^5 -println(s) - -# To get input from the console this can be done with the readline() function -# However getting console input when running in vscode with F5/shift+enter -# seems to crash for some reason, so avoid console input if thats how you -# run the program -# s = readline() -# println(s) diff --git a/2019/Julia/Code/5.arrays.jl b/2019/Julia/Code/5.arrays.jl deleted file mode 100644 index 69fa40a..0000000 --- a/2019/Julia/Code/5.arrays.jl +++ /dev/null @@ -1,133 +0,0 @@ - -# Lists/Arrays/Vectors work very similarly to python - -# A list can be constructed from a set of elements with [] brackets -l = [1, 2, 3, 4] - -@show typeof(l) - -# Indexing the array can be done with [] also. -# Keep in mind, arrays in julia are 1-indexed by default -@show l[2] - -# The type of elements in the array can be enforced by writing -# the type directly in front of the brackets -l = Int32[1, 2, 3, 4] - -@show typeof(l) - -# An array will try to implicitly convert data to have a single -# element data type -l = [1, 2.3, 3//2] - -@show l -@show typeof(l) - -# However if this is not possible, the list will get the type Any. -# Arrays with multiple types are much more inefficient because of -# type bookkeeping. -l = [1, 2.3, 3//2, "hello"] - -@show l -@show typeof(l) - -# Julia natively supports multidimensional arrays, such as matrices, tensors -# etc. with a lot of linear algebra built into the language. -m = [ - 1 2 3; - 4 5 6; - 7 8 9 -] - -display(m) # display() is a pretty-print function that is nice for showing - # matrices and other containers -@show typeof(m) - -# Creating an "empty" array can be done in a couple different ways - -# Creating an array with no elements is usually done with empty brackets [] -l = [] -# or with a specific type -l = Float32[] - -# Creating an uninitialized array with a set amount of elements -# can be achieved by calling the Array constructor - -l = Array{Int, 1}(undef, 100) # Creating a 1d array of 100 undefined elements - -# when working with 1d arrays it is usually better to use the alias Vector -# for 1d array. Vector{T} is an alias for Array{T, 1} - -l = Vector{Int}(undef, 100) # Does the exactly the same as line above - -# however it is usually cleaner and safer to use the function zeros() or -# ones() to initialize the memory. -l = zeros(Int, 100) # creates an array of 100 zeros of type Int -l = ones(Int, 100) # same for ones - -# Values can be added to the back of an array with the push! function. -l = [1, 2, 3, 4] -push!(l, 5) - -@show l - -# Reserving space in the buffer can be done with sizehint! -# That way pushing values to the array doesn't cause so many reallocations - -sizehint!(l, 100) # reserving space for 100 elements - -# Pushing to the front can be done with pushfirst! -pushfirst!(l, 0) - -@show l - -# Do not confuse push! with append!. Where append in python works as push! -# here, append! in julia concatenates a whole array to the back. -append!(l, [6, 7, 8, 9]) - -@show l - -# Deleting an element at a specific index is done by deleteat! -# Keep in mind that deleting elements from an array is often slow -# as data has to be moved. In julia it is fast to delete elements near -# either end of the array as the shortest end is the one moved to fill -# the space. -deleteat!(l, 3) - -@show l - -# As in python, list can be created with a list comprehension -l = [i^2 for i in 1 : 5] # creates square numbers from 1 to 25 -@show l - -# As Julia supports multidimensional arrays, it also supports -# multidimensional list comprehensions -l = [x * y for y in 1 : 3, x in 1 : 4] -display(l) - -# It is possible to view an array through a wrapper, making it differently -# organized without copying data, f.exs. the transpose of a matrix or -# viewing a multidimensional array as the raw memory as a 1d array. -# There are many different types of views in multiple different packages. -# search the documentation to see more - -l2 = view(l, 3:-1:1, 1 : 4) # Flipping the matrix upside down -display(l2) - -l2 = transpose(l) # transpose is a wrapper for a PermutedDimsArray -l2 = PermutedDimsArray(l, (2, 1)) # flips x and y dimensions -display(l2) - - -# Random numbers can be created in many different ways. Here are a fiew -# easy ones. - -a = rand(Int64) # Create a random Int64 -a = rand(Float64) # Create random Float64 in the range 0 : 1 -a = rand(1 : 10) # Create a random Int in the given range -l = rand(1 : 10, 3, 4) # Create a random 3x4 matrix with entries in 1 : 10 -display(l) - -using Random -rand!(l, -100 : 100) # Fill l with random entries from -100 : 100 -display(l) diff --git a/2019/Julia/Code/6.dicts.jl b/2019/Julia/Code/6.dicts.jl deleted file mode 100644 index 37c0ab1..0000000 --- a/2019/Julia/Code/6.dicts.jl +++ /dev/null @@ -1,45 +0,0 @@ - -# Dicts (dictionaries/maps) are not as simple as in python, resembling -# more the way modern c++ does it - -# Dicts are usually created from an array of "Pair" types (First => Last) -# The type of the dict keys and values are automatically infered. -d = Dict([ - "foo" => 3, - "bar" => 7 -]) -display(d) - -# A dict can also be initialized as an array of two tuples. This works -# identically to the example above -d = Dict([ - ("foo", 2.71), - ("bar", 3.14) -]) -display(d) - -# Values can be pushed to the dict similarly to an array. -# Keep in mind that creating an empty dict like this gives the type -# Dict{Any, Any} which might be somewhat slower because of having -# to work for general types -d = Dict() -push!(d, "foo" => 1//2) -push!(d, "bar" => 22//7) -display(d) - -# The problem above can be mitigated by infering the types manually -d = Dict{String, Rational{Int}}() -push!(d, "foo" => 1//2) -push!(d, "bar" => 22//7) -display(d) - -# A key can be deleted from a dict with delete!() -delete!(d, "foo") -display(d) - -# To check if a certain key exists in the dict, the haskey function is used -println(haskey(d, "foo")) # false -println(haskey(d, "bar")) # true - -# Indexing a dict is done with brackets like for any array -println(d["bar"]) diff --git a/2019/Julia/Code/7.sets.jl b/2019/Julia/Code/7.sets.jl deleted file mode 100644 index b189f44..0000000 --- a/2019/Julia/Code/7.sets.jl +++ /dev/null @@ -1,47 +0,0 @@ - -# Sets are created from lists of elements and duplicates are removed -s = Set(['a', 'b', 'c', 'b']) -display(s) -@show 'b' in s - -# As with other collections, elements can be added with push! -push!(s, 'd') -display(s) - -# And elements are removed with delete! -delete!(s, 'b') -display(s) - -# An empty set can be made just like an empty dict, but again this forces -# it to accept elements of type Any, which can be an minor slowdown -s = Set() - -# This is of course fixed by infering the type when creating the dict -s = Set{Int}() -push!(s, 2) -display(s) - -# Usual set operations like union, intersect, difference and checking if -# one is a subset of another, are all implemented, many with -# unicode infix operators -s1 = Set([1, 2, 4, 8, 16]) -s2 = Set([2, 3, 5, 16]) - -@show union(s1, s2) # Takes the set union -@show s1 ∪ s2 # Equvialent to the line above (\cup for the unicode macro) - -@show intersect(s1, s2) # Set intesect -@show s1 ∩ s2 # Unicode version (\cap) - -@show setdiff(s1, s2) # Set difference. No unicode replacement for this one -@show symdiff(s1, s2) # symetric difference. No unicode here either - -union!(s1, s2) # Equvialent to s1 = s1 ∪ s2 -@show s1 - -intersect!(s1, s2) # Equvialent to s1 = s1 ∩ s2 -@show s1 - -# Check if s1 is a subset of s2. (\subseteq) -@show s1 ⊆ s2 - diff --git a/2019/Julia/Code/8.controllflow.jl b/2019/Julia/Code/8.controllflow.jl deleted file mode 100644 index ebaa049..0000000 --- a/2019/Julia/Code/8.controllflow.jl +++ /dev/null @@ -1,61 +0,0 @@ - -a = 3 -b = 5 - -# if statements are made very similarly to other languages like python -if a < b - println("<") -elseif a > b - println(">") -else - println("=") -end - - -i = 10 - -# While loops are made similarly to if statements -while i >= 0 - print(i, ' ') - global i -= 1 -end - -println() - -l = [] - -# A typical range based for loop is made similarly to python -# with matlab style range syntax -for i in 1 : 10 - push!(l, i^2) -end -println(l) - -# A for-each style for loop is also similar to python -for i in l - print(i, ' ') -end -println() - -# Reverse ranges can be achieved by specifying the steplength as the -# middle argument in the range -for i in length(l) : -1 : 1 - print(l[i], ' ') -end -println() - -# A reverse for-each loop can be achieved a couple different ways. -# Perhaps the cleanest way is to just create the reverse array and -# iterating over that. This however copies the whole array to a new -# reversed one, so it is a bit memory inefficient. -for i in reverse(l) - print(i, ' ') -end -println() - -# This problem can be mitigated by using an array view that views the -# array in reverse. This is fine, but it doesn't look as clean anymore. -for i in view(l, length(l) : -1 : 1) - print(i, ' ') -end -println() diff --git a/2019/Julia/Code/9.scopes.jl b/2019/Julia/Code/9.scopes.jl deleted file mode 100644 index 50a3eb5..0000000 --- a/2019/Julia/Code/9.scopes.jl +++ /dev/null @@ -1,59 +0,0 @@ -# The global scope in julia behaves weirdly. This section shows how to -# cicumvent the issues that arise, but the bottom line here should be -# to avoid the global scope as much as humanly possible. -# Changing globals require ugly explicit syntax, globals cannot be -# strongly typed, and, in general, globals are significantly slower -# up to several orders of magnitude in some cases. - -a = 5 - -# This works -if a > 2 - println(a) - a += 3 -end - - -for i in 1 : 3 - println(a) # This works - # a -= 1 # This does not work -end - -# Declaring a to be global fixes this problem -for i in 1 : 3 - global a - println(a) - a -= 1 -end - -# None of this is a problem in functions, so do everything in functions -function main() - a = 7 - for i in 1 : 3 - a -= 1 - end - println(a) -end - -main() - -# An inline function body can be created with a "let" block. -# This creates a nameless function that is run immediately. -let a = 10 - for i in 1 : 3 - a -= 1 - end - println(a) -end - - -# A "begin" block is similar to a let block, but it does not enforce -# a new scope, so this code is still in the global scope -begin - a = 12 - for i in 1 : 3 - global a -= 1 - end - println(a) -end - diff --git a/2019/Julia/LiveCode/test.jl b/2019/Julia/LiveCode/test.jl deleted file mode 100644 index 3f4ab44..0000000 --- a/2019/Julia/LiveCode/test.jl +++ /dev/null @@ -1 +0,0 @@ -println("Hello World!") \ No newline at end of file diff --git a/2019/Julia/README.md b/2019/Julia/README.md deleted file mode 100644 index fa90edd..0000000 --- a/2019/Julia/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# JuliaKursPVV -All the files used in the Julia Course for PVV. diff --git a/2019/PythonIntro/README.md b/2019/PythonIntro/README.md deleted file mode 100644 index 0b41bec..0000000 --- a/2019/PythonIntro/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Notes for introductory to Python - -The cource was held by Torstein N-H 27.09.2019. -These notes were used loosely and are included for future reference. diff --git a/README.md b/README.md index 398b4eb..0b41bec 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -# Kurs på PVV - -Dette er et enkelt lite repository for å samle tidligere kursmateriale. - +# Notes for introductory to Python +The cource was held by Torstein N-H 27.09.2019. +These notes were used loosely and are included for future reference. diff --git a/2019/PythonIntro/notes/00_toolchain.md b/notes/00_toolchain.md similarity index 100% rename from 2019/PythonIntro/notes/00_toolchain.md rename to notes/00_toolchain.md diff --git a/2019/PythonIntro/notes/01_introduction.py b/notes/01_introduction.py similarity index 100% rename from 2019/PythonIntro/notes/01_introduction.py rename to notes/01_introduction.py diff --git a/2019/PythonIntro/notes/02_controlFlow.py b/notes/02_controlFlow.py similarity index 100% rename from 2019/PythonIntro/notes/02_controlFlow.py rename to notes/02_controlFlow.py diff --git a/2019/PythonIntro/notes/03_functions.py b/notes/03_functions.py similarity index 100% rename from 2019/PythonIntro/notes/03_functions.py rename to notes/03_functions.py diff --git a/2019/PythonIntro/notes/04_1_objectorientation.py b/notes/04_1_objectorientation.py similarity index 100% rename from 2019/PythonIntro/notes/04_1_objectorientation.py rename to notes/04_1_objectorientation.py diff --git a/2019/PythonIntro/notes/04_2_makingObjects.py b/notes/04_2_makingObjects.py similarity index 100% rename from 2019/PythonIntro/notes/04_2_makingObjects.py rename to notes/04_2_makingObjects.py diff --git a/2019/PythonIntro/notes/05_1_datastructures.py b/notes/05_1_datastructures.py similarity index 100% rename from 2019/PythonIntro/notes/05_1_datastructures.py rename to notes/05_1_datastructures.py diff --git a/2019/PythonIntro/notes/05_2_usefulFunctions.py b/notes/05_2_usefulFunctions.py similarity index 100% rename from 2019/PythonIntro/notes/05_2_usefulFunctions.py rename to notes/05_2_usefulFunctions.py diff --git a/2019/PythonIntro/notes/06_io.py b/notes/06_io.py similarity index 100% rename from 2019/PythonIntro/notes/06_io.py rename to notes/06_io.py diff --git a/2019/PythonIntro/notes/07_importing.py b/notes/07_importing.py similarity index 100% rename from 2019/PythonIntro/notes/07_importing.py rename to notes/07_importing.py diff --git a/2019/PythonIntro/notes/file.txt b/notes/file.txt similarity index 100% rename from 2019/PythonIntro/notes/file.txt rename to notes/file.txt diff --git a/2019/PythonIntro/notes/kurstekst.txt b/notes/kurstekst.txt similarity index 100% rename from 2019/PythonIntro/notes/kurstekst.txt rename to notes/kurstekst.txt diff --git a/2019/PythonIntro/notes/newFile.txt b/notes/newFile.txt similarity index 100% rename from 2019/PythonIntro/notes/newFile.txt rename to notes/newFile.txt diff --git a/2019/PythonIntro/notes/requirements.txt b/notes/requirements.txt similarity index 100% rename from 2019/PythonIntro/notes/requirements.txt rename to notes/requirements.txt diff --git a/2019/PythonIntro/notes/tempCodeRunnerFile.py b/notes/tempCodeRunnerFile.py similarity index 100% rename from 2019/PythonIntro/notes/tempCodeRunnerFile.py rename to notes/tempCodeRunnerFile.py