text:
#!/usr/bin/env julia

"""
FADU.jl - Feature Aggregate Depth Utility.

Description - Generate fractional counts of alignments that map to non-overlapping portions of genes
Requires (version number listed is earliest supported version):
    Julia - v1.4.2
    * Packages *
    BGZFStreams.jl - v0.3.0
    GenomicFeatures.jl - v2.0.0
    GFF3 - 0.1.0
    Indexes.jl - v0.1.1
    StructArrays.jl - v0.4.4
    XAM.jl - v0.2.6

By: Shaun Adkins (sadkins@som.umaryland.edu)
    Matthew Chung (mattchung@umaryland.edu)

"""

# The macro on modules and functions makes the code available to all worker processes
using ArgParse
using XAM: BAM, SAM
using GenomicFeatures
using GFF3
using Indexes
using Printf
using StructArrays

include("alignment_overlaps.jl")
include("bam_record.jl")
include("feature_counts.jl")
include("gff_feature.jl")

const VERSION_NUMBER = "1.8"    # Version number of the FADU program
const MAX_FRAGMENT_SIZE = 1000 # Maximum size of fragment.  If exceeded, fragment will be considered two reads
const EM_ITER_DEFAULT = 1 # Number of iterations to do EM-algorithm

### Functions to clean up, then move to their proper "include" script

########
# Main #
########

function parse_commandline()
    s = ArgParseSettings(description = "Generate counts of reads that map to non-overlapping portions of genes",
    prog = "fadu.jl",
	version = VERSION_NUMBER,
	add_version = true,
    add_help = true)

    # The macro to add a table of arguments and options to the ArgParseSettings object
    @add_arg_table! s begin
        "--bam_file", "-b"
            help = "Path to BAM file (SAM is not supported)."
            metavar = "/path/to/file.bam"
            required = true
        "--gff3_file", "-g"
            help = "Path to GFF3-formatted annotation file (GTF is not supported)."
            metavar = "/path/to/annotation.gff3"
            required = true
        "--output_dir", "-o"
            help = "Directory to write the output."
            metavar = "/path/to/output/dir/"
            required = true
        "--stranded", "-s"
            help = "Indicate if BAM reads are from a strand-specific assay. Choose between 'yes', 'no', or 'reverse'."
            default = "no"
        "--feature_type", "-f"
            help = "Which GFF3/GTF feature type (column 3) to obtain. readcount statistics for. Case-sensitive."
            default = "gene"
        "--attribute_type", "-a"
            help = "Which GFF3/GTF feature type (column 9) to obtain. readcount statistics for. Case-sensitive."
            default = "ID"
        "--keep_only_proper_pairs", "-p"
            help = "If enabled, keep only properly paired reads when performing calculations."
            action = :store_true
            dest_name = "pp_only"
        "--max_fragment_size", "-m"
            help = "If the fragment size of properly-paired reads exceeds this value, process pair as single reads instead of as a fragment. Setting this value to 0 will make every fragment pair be processed as two individual reads. If --keep_only_proper_pairs is enabled, then any fragment exceeding this value will be discarded."
            default = MAX_FRAGMENT_SIZE
            arg_type = Int
            range_tester = (x->typemin(UInt)<=x<=typemax(UInt))
        "--remove_multimapped", "-M"
            help = "If enabled, remove any reads or fragments that are mapped to multiple regions of the genome, indiated by the 'NH' attribute being greater than 1.  Otherwise, use EM algorithm to quantify reads after all other reads are counted."
            action = :store_true
            dest_name = "rm_multimap"
        "--em_iterations", "-e"
            help = "Number of iterations to perform EM algorithm on multimapped read depth. Only applies if --remove_multimapped flag is not passed (is disabled)"
            default = EM_ITER_DEFAULT
            arg_type = Int
            range_tester = (x->x>0)
            dest_name = "em_iter"

    # Will not add log_file or debug options for now
    end
    # Converts the ArgParseSettings object into key/value pairs
    return parse_args(s)
end

function validate_args(args)
    """Validate the passed arguments."""
    isfile(args["gff3_file"]) || throw(FileNotFoundException("GFF3 file does not seem to exist. Please check supplied path."))
    isfile(args["bam_file"]) || throw(FileNotFoundException("BAM file does not seem to exist. Please check supplied path."))
    if !isdir(args["output_dir"])
        @debug("Creating output directory")
        mkdir(args["output_dir"])
    end
    args["stranded"] in ["yes", "no", "reverse"] || error("--stranded argument must be either 'yes', 'no', or 'reverse'.")
end

function main()
    args = parse_commandline()
    validate_args(args)
    @info("Parsed args:")
    for (arg,val) in args
        @info("  $arg  =>  $val")
    end

    @info("Processing annotation features...")
    features = try
        open(collect, GFF3.Reader, args["gff3_file"])    # Array of GFF3.Record objects
    catch e
        println(stderr, "ERROR: GFF3 file was unable to be read, due to possible improper formatting.  Please consult https://github.com/The-Sequence-Ontology/Specifications/blob/master/gff3.md for how to properly format the GFF3 file.  Actual error is below.  Program will now exit.\n")
        showerror(stderr, e)
        println(stderr, "")
        exit(1)
    end

    # Only keep features for the chosen feature type
    filter!(x -> GFF3.featuretype(x) == args["feature_type"], features)

    @info("Getting unique coordinates per contig and feature...")
    uniq_coords = create_uniq_coords_dict(features, args["stranded"])

    @info("Initializing dictionary of feature count information")
    feat_overlaps = create_feat_overlaps_dict(features, uniq_coords, args["attribute_type"], args["stranded"])

    bai_file = replace(args["bam_file"], ".bam" => ".bai")
    # Attempt to find index file for BAM file in same directory
    if !isfile(bai_file)
        bai_file = args["bam_file"] * ".bai"
        if !isfile(bai_file)
            bam = args["bam_file"]
            error("Attempted to find index file for BAM file $bam but could not find one")
        end
    end
    @debug("Found BAM index file at $bai_file")

    # Open a BAM file and iterate over records overlapping GFF features.
    @info("Opening BAM alignment file...")
    reader = open(BAM.Reader, args["bam_file"], index = bai_file)

    @info("Now finding overlaps between alignment and annotation records...")
    multimapped_dict = process_all_feature_overlaps(feat_overlaps, features, reader, args)
    close(reader)

    # If multimapped reads are kept, use EM algorithm to count and re-add back into the feature counts
    if !args["rm_multimap"]
        num_multimaps = length(collect(keys(multimapped_dict)))
        @debug("Multimapped alignment templates: ", num_multimaps)

        featurenames = collect(keys(feat_overlaps))
        mm_feat_overlaps = Dict{String, FeatureOverlap}(featurename => initialize_overlap_info(coordinate_set(feat_overlaps[featurename])) for featurename in featurenames)

        @info("Counting and adjusting multimapped alignment feature counts via Expectation-Maximization algorithm...")
        while args["em_iter"] > 0
            @debug("\tEM iterations left: ", args["em_iter"])
            adjusted_overlaps = merge_mm_counts(feat_overlaps, mm_feat_overlaps, false)
            args["em_iter"] -= 1
            mm_feat_overlaps = compute_mm_counts_by_em(adjusted_overlaps, multimapped_dict, args)
        end
        # Last iteration the alignment counts are added too
        merge_mm_counts!(feat_overlaps, mm_feat_overlaps, true)
    end

    # Calculate sum of all counts for each feature
    totalcounts = calc_totalcounts(feat_overlaps)

    @info("Writing counts output to file...")
    out_file = joinpath(args["output_dir"], splitext(basename(args["bam_file"]))[1]) * ".counts.txt"
    out_f = open(out_file, "w")
    write(out_f, "featureID\tuniq_len\tnum_alignments\tcounts\ttpm\n")
    # Write output, sorted alphabetically
    for featurename in sort(collect(keys(feat_overlaps)))
        uniq_len::UInt = length(coordinate_set(feat_overlaps[featurename]))
        num_alignments = totalalignments(feat_overlaps[featurename])
        feat_counts = featurecounts(feat_overlaps[featurename])
        if isnan(feat_counts)
            feat_counts = zero(Float32)
        end
        tpm = calc_tpm(uniq_len, totalcounts, feat_counts)
        if isnan(tpm)
            tpm = zero(Float32)
        end
        s = @sprintf("%s\t%i\t%.1f\t%.2f\t%.2f\n", featurename, uniq_len, num_alignments, feat_counts, tpm)
        write(out_f, s)
    end
    close(out_f)

    @info("FADU is complete!  Exiting!")
end

main()
exit()

max_stars_repo_name: IGS/FADU

max_issues_repo_name: adkinsrs/FADU

max_forks_repo_name: adkinsrs/FADU


text:
module NSDE

using Reexport
@reexport using NSDEBase
@reexport using RungeKutta
@reexport using LinearMultistep
@reexport using TimeParallel
@reexport using MovingWindow
@reexport using FiniteDifference
@reexport using FiniteVolume
@reexport using FiniteElement
@reexport using Spectral

end

ext: jl


text:
# This file is a part of Julia. License is MIT: https://julialang.org/license

module FakePTYs

function open_fake_pty()
    @static if Sys.iswindows()
        error("Unable to create a fake PTY in Windows")
    end

    O_RDWR = Base.Filesystem.JL_O_RDWR
    O_NOCTTY = Base.Filesystem.JL_O_NOCTTY

    fdm = ccall(:posix_openpt, Cint, (Cint,), O_RDWR|O_NOCTTY)
    fdm == -1 && error("Failed to open PTY master")
    rc = ccall(:grantpt, Cint, (Cint,), fdm)
    rc != 0 && error("grantpt failed")
    rc = ccall(:unlockpt, Cint, (Cint,), fdm)
    rc != 0 && error("unlockpt")

    fds = ccall(:open, Cint, (Ptr{UInt8}, Cint),
        ccall(:ptsname, Ptr{UInt8}, (Cint,), fdm), O_RDWR|O_NOCTTY)

    # slave
    slave = RawFD(fds)
    master = Base.TTY(RawFD(fdm); readable = true)
    slave, master
end

function with_fake_pty(f)
    slave, master = open_fake_pty()
    try
        f(slave, master)
    finally
        ccall(:close,Cint,(Cint,),slave) # XXX: this causes the kernel to throw away all unread data on the pty
        close(master)
    end
end

end

max_stars_repo_name: greimel/julia

max_issues_repo_name: greimel/julia

max_forks_repo_name: greimel/julia


text:
@testset "Regularization" begin
    for (constructor, copier) in ((interpolate, identity), (interpolate!, copy))
        isinplace = constructor == interpolate!
        f0(x) = sin((x-3)*2pi/9 - 1)
        f1(x) = 1.0 + 0.1*x + 0.01*x^2 + 0.001*x^3

        xmax = 10
        xi = range(0, stop=xmax, length=11)
        xfine = range(0, stop=xmax, length=101)

        A0 = f0.(xi)
        A1 = f1.(xi)

        for (yi, f) in ((A0, f0), (A1, f1)), λ in (0.01, 100), k in (1, 2, 3, 4)
            it = @inferred(interpolate(yi, BSpline(Cubic(Line(OnCell()))), λ, k))
            itt = @inferred(scale(it, xi))

            if f === f0
                if λ == 0.01
                    # test that interpolation of the interpolating points is close to expected data
                    for x in [2, 3, 6, 7]
                        @test f(x) ≈ itt(x) atol=0.01
                    end
                elseif λ == 100
                    # test that interpolation of the interpolating points is far from expected data
                    for x in [2, 3, 6, 7]
                        @test !(isapprox(f(x), itt(x); atol=0.1))
                    end
                end

            elseif f === f1
                if k==4
                    for x in xfine
                        # test that interpolation is close to expected data when
                        # the smoothing order is higher than the polynomial order
                        @test f(x) ≈ itt(x) atol=0.1
                    end
                end
            end
        end

        # Check fallback to no regularization for λ=0
        itp1  = @inferred(constructor(copier(A0), BSpline(Cubic(Line(OnGrid()))), 0, 1))
        itp1p = @inferred(constructor(copier(A0), BSpline(Cubic(Line(OnGrid())))))
        @test itp1 == itp1p

        f2(x, y) = sin(x/10)*cos(y/6)
        xmax2, ymax2 = 30, 10
        A2 = Float64[f2(x, y) for x in 1:xmax2, y in 1:ymax2]

        # Check fallback to no regularization for non Vectors
        itp2  = @inferred(constructor(copier(A2), BSpline(Cubic(Line(OnGrid()))), 1, 1))
        itp2p = @inferred(constructor(copier(A2), BSpline(Cubic(Line(OnGrid())))))
        @test itp2 == itp2p
    end
end


text:
# following http://en.wikipedia.org/w/index.php?title=Centimetre%E2%80%93gram%E2%80%93second_system_of_units&oldid=569933131
const CentiMeter = BaseUnit("m", prefix=-2)
const Second = BaseUnit("s")
const Gram = BaseUnit("g")
const Kelvin = BaseUnit("K")

const Dyne = DerivedUnit("dyn",Gram*CentiMeter*Second^-2)
const Erg = DerivedUnit("erg", Gram*CentiMeter^2*Second^-2)
const Barye = DerivedUnit("Ba", Gram/(CentiMeter*Second^2))
const Poise = DerivedUnit("P", Gram/(CentiMeter*Second))
const Stokes = DerivedUnit("St", CentiMeter^2/Second)
const StatCoulomb = DerivedUnit("Fr", (Erg*CentiMeter)^(0.5))

const c_light = 29979245800*CentiMeter/Second
const C_light = DerivedUnit("c",c_light)
const k_boltzmann = 1.3806488e-16*Erg/Kelvin
const h_planck = 6.62606957e-37*Erg*Second
const hbar_planck = h_planck/2π
const g_gravitation = 6.67428e-8*CentiMeter^3*Gram^-1*Second^-2
const e_electron = 4.80320427e-10*StatCoulomb
const m_electron = 9.10938215e-28*Gram
const a_bohr = 5.2917721092e-9*CentiMeter
const u_bohr = e_electron*hbar_planck/(2*m_electron)
const alpha_fine_structure = 7.2973525698e-3

const Franklin = StatCoulomb

const Ohm = DerivedUnit("Ω", Volt/Ampere)

export CentiMeter, Second, Gram, Kelvin
export Dyne, Erg, Barye, Poise, Stokes, StatCoulomb
export c_light, C_light, k_boltzmann, h_planck, g_gravitation, e_electron
export m_electron, a_bohr, u_bohr, alpha_fine_structure


text:
### A Pluto.jl notebook ###
# v0.16.1

using Markdown
using InteractiveUtils

# ╔═╡ e8595a60-222f-11ec-0595-c9717ac06507
begin
	using Plots,SymPy, LaTeXStrings, LinearAlgebra
	import PlotlyJS
	plotlyjs()
end

# ╔═╡ 431922d9-e97a-4300-a482-2d458b66c67a
md""" ### Ejercicio 1
Considere la cónica dada por $y = x^2 − 4x + 5$ y la recta $L$ que pasa por $(2, 7)$ con
direcci´on $v = (1, 1)$
"""

# ╔═╡ 85cf0b95-4446-4e84-a6c3-f9d3fcf4cd61
md"""
1. En un mismo plano cartesiano grafique la recta y la c´onica, obtenga anal´ıticamente los
puntos de intersecci´on entre ambas y m´arquelos en su gr´afico.

2. Halle el ´area del tri´angulo definido por el v´ertice de la c´onica y los puntos de intersecci´on
obtenidos anteriormente.
"""

# ╔═╡ 53b8d020-b4a9-4c74-b0cc-dba03b6edbd3
# Definimos las variables s'imbolicas
@syms x λ

# ╔═╡ 4257606e-3eff-4124-aad3-517998f97d24
md"""
Definamos la conica
"""

# ╔═╡ 61b1bf99-507b-4379-b537-86ce040f1418
y = x^2 - 4x + 5

# ╔═╡ d17a8914-6ecf-4606-a664-7242d0f8f06c
md"""
Para la  recta tenemos la siguiente representaci'o

$$L  = \lambda (1, 1) + (2, 7)$$

pero para encontrar la interseccion con la par'abola va a ser m'as 'util representarlo en la forma can'onica de $y = m * x + b$

$$(x,y) = ( \lambda + 2, \lambda + 7 )$$

Igualando cada una de las componentes tenemos que

$$y = \lambda + 7 = (x-2) + 7 = x + 5$$
"""

# ╔═╡ 2056778d-12f0-4325-920f-f6c7e453918b
L =	x + 5

# ╔═╡ 4f6feaf8-5322-4afc-b31d-211761e222c2
md"""
Graficando ambas
"""

# ╔═╡ f676a35a-c61e-4547-b176-211dd3dc647b
begin
	p = plot()
	plot!(y,label=sympy.latex(y),xlims=(-2,6))
	plot!(L, label=sympy.latex(L))
end

# ╔═╡ d8e3eda0-cada-4047-81cc-137a54e1b5e6
md"""
Calculamos la intersecci'on entre la recta y la para'bola

`solve` busca las soluciones del sistema $S = 0$ entonces planteamos la igualdad como
$S = L - y = 0$ que es equivalente a tener $L=y$
"""

# ╔═╡ 897cfd67-1be7-40e4-87d9-c11bc9de55d4
interseccion = solve(y - L)

# ╔═╡ 67e7f9f5-6e78-4579-97f7-7c0349b39afd
y_interseccion = y.(interseccion)

# ╔═╡ 4d6550b8-4e9d-4437-84bd-d978e33bfdb8
md"""
Agregamos los puntos de la intersecci'on al gr'afico
"""

# ╔═╡ 997c5ff7-ac5d-484f-bcdf-a89194d112ee
p2 = scatter!(interseccion,y_interseccion,color=:black,label="interseccion",ax=p)

# ╔═╡ 19f1f8b8-0f5c-4388-b550-f4cdd7619311
md"""
Calculamos el vertice usando la formula de $x_{vert} = \frac{-b}{2a}$
y en nuestro caso queda

$$x_{vert} = \frac{-(-4)}{2*1} = 2$$
$$y_{vert} = y(x_{vert}) = 2^{2} - 4 * 2 + 5 = 4 - 8 + 5 = 1$$
"""

# ╔═╡ 8e1588d8-1d7a-4151-b8a1-afc3c1298887
p3 = scatter!([2],[1],color=:green,label="vertice",ax=p2)

# ╔═╡ 09baa7ce-fc86-42a5-8130-3c8125c93f5b
md"""
Entonces ya tenemos los tres vertices del triangulo
"""

# ╔═╡ 653aa355-0c9d-4520-befd-d3f91678ffaa
begin
	# defino con decimales por una cuestion del programa
	v₁ = [0.0, 5.0]
	v₂ = [5.0, 10.0]
	v₃ = [2.0, 1.0]
	nothing
end

# ╔═╡ 1938fc99-5366-4bc0-a2b3-892d7281db93
md"""
Ahora para hallar el area vamos a utilizar el determinante entre dos vectores que definan el triangulo. Voy a considerar los vectores que van desde el vertice $v_{3}$ a los dos puntos de las intersecciones, abusando un poco la notacion $V_{1,3} = v_{1} - v_{3}$, $V_{1,3} = v_{2} - v_{3}$
"""

# ╔═╡ 0f723758-c34e-4a3b-ad72-853cc23b29fc
m = [v₁-v₃ v₂-v₃]

# ╔═╡ 253ae086-b3b0-4243-b05d-4e575166aa53
det(m)

# ╔═╡ 9003d85b-eaf0-44f9-b2b7-1dd990e4fd76
md"""
El determinante es negativo porque estamos tomando como primer vector el que est'a m'as a la izquierda. Si invertimos el orden en el que armamos la matriz, el determinante va a dar positivo, estamos alternando dos columnas :)

En conclusion el a'rea es el valor absoluto del determinante dividido dos, entonces tenemos que

``area =`` $(abs(det(m))/2)
"""

# ╔═╡ c18c2f4b-1e5f-463f-8464-0a6387896efc
md"""
## Ejercicio 2.

Sean $\pi : x + 2y + 2z = 12$ y $P = (1, 0, 1)$.

a) Hallar el punto de π que se encuentra a menor distancia del punto P y calcular la distancia
de $P$ al plano $\pi$.

b) Hallar el volumen del tetraedro (pir´amide de base triangular) definido por P y las intersecciones del plano π con los ejes coordenados. (Recuerde que el volumen del tetraedo es un
sexto del volumen del paralelep´ıdedo)
"""

# ╔═╡ 0f3486cc-8de9-452c-a0a1-b8c5277c1592
n = [1, 2, 2]

# ╔═╡ f4ee2c3e-7a1b-4d4a-99cf-0dda3ae572d7
P = [1,0,1]

# ╔═╡ cf0c4904-6b99-4af7-8aee-d03593bc2091
L₂ = λ*n + P

# ╔═╡ e86f3da1-ab64-4582-9fc7-8f12966c318f
π(v) = n ⋅ v - 12

# ╔═╡ 84f78af9-2866-404e-a121-3e3c6afe617b
# SymMatrix esta indexada desde 0 :(
π(L₂)

# ╔═╡ 9bf041fa-c284-4425-831c-2d8a207e54e2
λₛₒₗ = solve(π(L₂))[1]

# ╔═╡ 512fadab-9352-4d45-b73e-d754b30114e4
Q = subs.(L₂,λ => λₛₒₗ)

# ╔═╡ 6612a222-06c1-47a8-b024-146ca8caea08
md"""
Un poco de sanity check, comprobamos que $Q \in \pi$
"""

# ╔═╡ 604e2572-57d6-4076-b4bc-35adcceb7994
π(Q)

# ╔═╡ ef868e86-0a6a-47fb-b2a5-d9190cd03c0a
md"""
Con esto ya podemos calcular la distancia entre $P$ y $Q$
"""

# ╔═╡ 74bf0f00-bc45-4d26-9c61-f164de3d21e0
md"""
``dist(P,Q) = \vert P- Q \vert =`` $(norm(P - Q))
"""

# ╔═╡ 50432a00-fdbe-448e-a6c1-89b1d01d435d
md"""
#### b) Buscamos la interseccion de $\pi$ con los ejes coordenados
"""

# ╔═╡ 4bf801a5-b443-46d1-a110-ab8096527116
md"""
Primero definimos el vector can'onico en una direccio'on
"""

# ╔═╡ 2136e05b-bef2-4dc8-8723-3fbb8360cba0
e₁ = [1,0,0]

# ╔═╡ 5532b807-94e2-4ff2-9b65-41d1423863c6
md"""
Como queremos encontrar la intersecci'on entre el eje y el plano, definimos la recta que sigue al eje coordenado como
"""

# ╔═╡ 904d25d1-2244-4f76-ac1c-b1fef76ff41a
λ * e₁

# ╔═╡ 2ba19d1c-f22e-47c8-b81c-979e0edd7348
md"""
Cuando lo evaluamos en la definici'on del plano tenemos que la interseccio'n occurre cuando la siguiente es igual a $0$
"""

# ╔═╡ 9eeb302c-a277-437d-9e95-345b72d1a3a4
π(λ * e₁)

# ╔═╡ 15949e72-93cf-4aa6-8524-5b55fe9eb229
md"""
Y eso ocurre cuando ``\lambda =`` $(solve(π(λ * e₁)))
"""

# ╔═╡ 6935e6f6-e926-4766-89a4-8d86408cc15d
interseccion_con_π(v) = solve(π(λ * v))[1]

# ╔═╡ aed97c10-bcae-4552-b522-afb0a6073c7a
md"""
Extendemos el c'alculo de la intersecci'on del plano con los otros dos ejes obteniendo los siguentes puntos
"""

# ╔═╡ 760596e6-3937-4024-b3b4-7bfae97c4a4f
begin
	e₂ = [0,1,0]
	e₃ = [0,0,1]
	x₁ = interseccion_con_π(e₁) * e₁
	x₂ = interseccion_con_π(e₂) * e₂
	x₃ = interseccion_con_π(e₃) * e₃
	x₁, x₂, x₃
end

# ╔═╡ 64d47104-23e7-492c-aa5e-c6eee7f6d10d
md"""
Para tener un poco m'as de intuici'on los graficamos
"""

# ╔═╡ ff31fe54-2f96-4e12-bf62-395dd29fa515
begin
	figura = scatter3d([P[1]],[P[2]],[P[3]],label="P",xlabel="x",ylabel="y",zlabel="z")
	for p in [x₁, x₂, x₃]
		scatter3d!([p[1]],[p[2]],[p[3]],label=false,ax=figura)
	end
	figura
end

# ╔═╡ 6867d0da-516e-4924-b3f3-be7bbe75d4fc
md"""
Para calcular el volumen primero consideramos los vectores que van de $P$ a cada uno de los tres puntos $V_{i}$ que encontramos antes. Para eso calculamos $V_{i} - P$, para cada uno de los ejes y los ordenamos a cada uno como una columna de una matriz de manera de que podamos calcular el determinante
"""

# ╔═╡ 9ca33e7d-aa40-4970-9072-bcf0f754ec04
M = [x₁ x₂ x₃] .- P

# ╔═╡ fe385398-3bd1-4662-8411-e2c9beda9a9f
md"""
Que tiene el determinante igual a
"""

# ╔═╡ 672d62df-7c33-4260-8c4f-a72e8a900bd3
det(M)

# ╔═╡ c389944d-1d91-44aa-a28d-d0848bb10228
md"""
Usando la ayuda del enunciado tenemos que el volumen del tetaedro es ``\frac{\vert det(M)\vert}{6} = `` $(det(M)/6)
"""

# ╔═╡ e7d5a0e0-0b6b-4012-88cd-7e50283fb721
md"""
### Ejercicio 3.

Para $\alpha \in \mathbb{R}$ considere la matriz $A \in \mathbb{R}^{3×3}$ dada por

$\left[
\begin{array}{rrr}
 1       & 0          & \alpha     \\
 \alpha  & \alpha - 1 & \alpha^{2} \\
 0       & 1          & \alpha - 2
\end{array}\right]$

1. Halle todos los valores de $\alpha$ para los cuales $A^{2021} − A^{2022}$ no resulte inversible.

2. Ponga $\alpha = 2$. Utilice el m´etodo de Gauss para resolver

$$Ax = e_{1} + e_{2} − e_{3}$$

`INDICANDO TODAS LAS OPERACIONES DE FILAS QUE UTILIZA. Exhiba la solucien forma param´etrica y la matriz escalonada reducida del sistema; se˜nale el rango de
A.`
"""

# ╔═╡ fc2349c9-fb1f-4ce3-94fc-adb98f3170b8
# Definimos el simbolo
@syms α

# ╔═╡ 30e16586-b504-4332-9f6c-cdeb3f9c686c
A = [1 0 α;
	α α-1 α^2;
	0 1 α-2]

# ╔═╡ 2f8356bc-311a-4826-861e-4852ed01bca1
md"""
El ejercicio nos pide que calculemos cuando la siguiente matriz no es inversible $A^{2021} − A^{2022}$, lo cual parece una locura. Pero recordemos que una manera de evaluar si una matriz es inversible es a partir del determinante. Y la matriz va a ser inversible en el caso de que su determinante sea distinto de 0
"""

# ╔═╡ 45d7938f-a9ff-4a21-b0f8-74a7b69e1a3d
md"""
$\begin{align}
det(A^{2021} − A^{2022}) &= det( A^{2021}*(I-A)  ) \\
                         &= det( A^{2021} ) * det(I-A)\\
                         &= det( A )^{2021} * det(I-A)
\end{align}$
"""

# ╔═╡ af547106-640f-4d89-b96d-b1d625822697
I - A

# ╔═╡ a2779834-7808-4bad-a97a-bc90dba2adc7
determinante = det(A)^2021 * det(I-A)

# ╔═╡ d9ef00bd-1ac5-4406-9cb7-ae9d90d2387e
md"""
El determinante se anula en el caso de que cualquiera de los terminos sea igual a cero, entonces tenemos que
"""

# ╔═╡ 76c7aed0-4bac-4a03-8a07-00583c571c52
solve(det(A))

# ╔═╡ 180d6fe0-baeb-4c05-bfc9-213a6f1ec07c
solve(det(I-A))

# ╔═╡ a7da009c-b867-46d2-84a2-087287521aa8
md"""
Entonces es la matriz no es inversible si $\alpha \in \{0,1,2\}$
"""

# ╔═╡ 5522536b-a0df-41f8-8525-856923f49104
md"""
Para resolver el punto b), reemplazamos $\alpha = 2$. Notemos que es uno de los valores en los que el la matriz no era inversible, eso nos esta diciendo que el sistema no est'a completamete determinado.
"""

# ╔═╡ 337404a1-514b-4f40-9aa7-738d0c07d34f
Aₛ = subs.(A, α=>2)

# ╔═╡ 7dcb7519-f6cc-47b6-bbf2-1896a0053a85
md"""
Resolviendo el sistema por el metodo de Gauss-Jordan

$$A x = (1,1,-1)$$
"""

# ╔═╡ dd6b45de-fa40-4697-a372-d7f6a75bc704
md"""
Llegamos a que la solucion es el siguiente vector
"""

# ╔═╡ e052a4ad-90a0-4f7f-a1e7-a35b92270d74
Aₛ\[1,1,-1]

# ╔═╡ 65dcc377-8278-4c08-867b-012065989b1f
md"""
Que representa la recta

``
L_{s} = λ (-2,0,1) + (1,-1,0)
``
"""

# ╔═╡ c2c157cb-29fa-488b-a5dd-caef9e392c6b
md"""
### Ejercicio 4.

a) Sean $u, v \in \mathbb{R}^{2}$ dos vectores tales que $det(u, v) = 3$.
Hallar el ´area del paralelogramo determinado por los vectores $2u + 3v$ y $u − 4v$.

b) Decidir si la siguiente afirmaci´on es verdadera o falsa. Si es verdadera, dar una demostraci´on. Si es falsa, dar un contraejemplo.

Sean $L_{1}$ y $L_{2}$ son dos rectas en $R^{3}$

Si $L_{1} \cap L_{2} = \emptyset$, entonces $L_{1}$ y $L_{2}$ son paralelas.
"""

# ╔═╡ 1dd55ddd-2c09-4d8c-83d3-442ebcf0d579
# definimos los vectores simbolicos
begin
	@syms u[1:2] v[1:2]
end

# ╔═╡ 0bd81932-75a6-4b74-a264-bb16ae798a44
det([u v])

# ╔═╡ c3ca6592-a758-40fc-96c5-e8609071697f
det([2u+3v u-4v])

# ╔═╡ 279a2774-a565-4ffa-9577-b2e987abed37
simplify(det([2u+3v u-4v]) / det([u v]))

# ╔═╡ 1dd28947-9fa2-42bc-9666-6e1b5e12a147
md"""
En el punto **b)** La afirmación es **falsa**, pues pueden existir dos rectas que no sean paralelas y no tengan intersección

Por ejemplo, si tomamos:

$$L_{a} = \lambda_{a} (1,0,0) + (0,0,0)$$

$$L_{b} = \lambda_{b} (0,1,0) + (0,0,1)$$
"""

# ╔═╡ 2b0dc6fe-ae32-48c9-a400-ad5fb8fbef4e
Lₐ(λ) = λ*[1,0,0]

# ╔═╡ 40420c6d-122b-454d-9954-8ec29765f3f2
Lₚ(λ) = λ*[0,1,0] + [0,0,1]

# ╔═╡ be180c4f-177b-41a7-83d3-5a0220c9ad0e
begin
t = -1:1
# scatter3d(,)
end

# ╔═╡ 067ffcf8-a398-4e50-bcf7-5425906f4a87
collect(map(Array,zip(Lₐ.(t)...)))

# ╔═╡ a1ce3aac-6e19-4de0-bcd5-4e86b26aab71
let
x,y,z =	collect(zip(Lₐ.(t)...))
# plot3d([x],[y],[z],xlabel="x",ylabel="y",zlabel="z")
end

# ╔═╡ 3cf6ffc2-0f08-41f7-adaa-9fa22f585881
# Para referencia
repr("text/latex",A);

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
SymPy = "24249f21-da20-56a4-8eb1-6a02cf4ae2e6"

[compat]
LaTeXStrings = "~1.2.1"
PlotlyJS = "~0.18.7"
Plots = "~1.22.3"
SymPy = "~1.0.52"
"""

# ╔═╡ 00000000-0000-0000-0000-000000000002
PLUTO_MANIFEST_TOML_CONTENTS = """
# This file is machine-generated - editing it directly is not advised

[[Adapt]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "84918055d15b3114ede17ac6a7182f68870c16f7"
uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
version = "3.3.1"

[[ArgTools]]
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"

[[Artifacts]]
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"

[[AssetRegistry]]
deps = ["Distributed", "JSON", "Pidfile", "SHA", "Test"]
git-tree-sha1 = "b25e88db7944f98789130d7b503276bc34bc098e"
uuid = "bf4720bc-e11a-5d0c-854e-bdca1663c893"
version = "0.1.0"

[[Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

[[BinDeps]]
deps = ["Libdl", "Pkg", "SHA", "URIParser", "Unicode"]
git-tree-sha1 = "1289b57e8cf019aede076edab0587eb9644175bd"
uuid = "9e28174c-4ba2-5203-b857-d8d62c4213ee"
version = "1.0.2"

[[Blink]]
deps = ["Base64", "BinDeps", "Distributed", "JSExpr", "JSON", "Lazy", "Logging", "MacroTools", "Mustache", "Mux", "Reexport", "Sockets", "WebIO", "WebSockets"]
git-tree-sha1 = "08d0b679fd7caa49e2bca9214b131289e19808c0"
uuid = "ad839575-38b3-5650-b840-f874b8c74a25"
version = "0.12.5"

[[Bzip2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "19a35467a82e236ff51bc17a3a44b69ef35185a2"
uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0"
version = "1.0.8+0"

[[Cairo_jll]]
deps = ["Artifacts", "Bzip2_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "JLLWrappers", "LZO_jll", "Libdl", "Pixman_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "f2202b55d816427cd385a9a4f3ffb226bee80f99"
uuid = "83423d85-b0ee-5818-9007-b63ccbeb887a"
version = "1.16.1+0"

[[ChainRulesCore]]
deps = ["Compat", "LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "e8a30e8019a512e4b6c56ccebc065026624660e8"
uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
version = "1.7.0"

[[ColorSchemes]]
deps = ["ColorTypes", "Colors", "FixedPointNumbers", "Random"]
git-tree-sha1 = "a851fec56cb73cfdf43762999ec72eff5b86882a"
uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
version = "3.15.0"

[[ColorTypes]]
deps = ["FixedPointNumbers", "Random"]
git-tree-sha1 = "024fe24d83e4a5bf5fc80501a314ce0d1aa35597"
uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
version = "0.11.0"

[[Colors]]
deps = ["ColorTypes", "FixedPointNumbers", "Reexport"]
git-tree-sha1 = "417b0ed7b8b838aa6ca0a87aadf1bb9eb111ce40"
uuid = "5ae59095-9a9b-59fe-a467-6f913c188581"
version = "0.12.8"

[[CommonEq]]
git-tree-sha1 = "d1beba82ceee6dc0fce8cb6b80bf600bbde66381"
uuid = "3709ef60-1bee-4518-9f2f-acd86f176c50"
version = "0.2.0"

[[CommonSolve]]
git-tree-sha1 = "68a0743f578349ada8bc911a5cbd5a2ef6ed6d1f"
uuid = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2"
version = "0.2.0"

[[Compat]]
deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"]
git-tree-sha1 = "31d0151f5716b655421d9d75b7fa74cc4e744df2"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "3.39.0"

[[CompilerSupportLibraries_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"

[[Conda]]
deps = ["JSON", "VersionParsing"]
git-tree-sha1 = "299304989a5e6473d985212c28928899c74e9421"
uuid = "8f4d0f93-b110-5947-807f-2305c1781a2d"
version = "1.5.2"

[[Contour]]
deps = ["StaticArrays"]
git-tree-sha1 = "9f02045d934dc030edad45944ea80dbd1f0ebea7"
uuid = "d38c429a-6771-53c6-b99e-75d170b6e991"
version = "0.5.7"

[[DataAPI]]
git-tree-sha1 = "cc70b17275652eb47bc9e5f81635981f13cea5c8"
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
version = "1.9.0"

[[DataStructures]]
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "7d9d316f04214f7efdbb6398d545446e246eff02"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.18.10"

[[DataValueInterfaces]]
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
version = "1.0.0"

[[Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"

[[DelimitedFiles]]
deps = ["Mmap"]
uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab"

[[Distributed]]
deps = ["Random", "Serialization", "Sockets"]
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"

[[DocStringExtensions]]
deps = ["LibGit2"]
git-tree-sha1 = "a32185f5428d3986f47c2ab78b1f216d5e6cc96f"
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
version = "0.8.5"

[[Downloads]]
deps = ["ArgTools", "LibCURL", "NetworkOptions"]
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"

[[EarCut_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "3f3a2501fa7236e9b911e0f7a588c657e822bb6d"
uuid = "5ae413db-bbd1-5e63-b57d-d24a61df00f5"
version = "2.2.3+0"

[[Expat_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b3bfd02e98aedfa5cf885665493c5598c350cd2f"
uuid = "2e619515-83b5-522b-bb60-26c02a35a201"
version = "2.2.10+0"

[[FFMPEG]]
deps = ["FFMPEG_jll"]
git-tree-sha1 = "b57e3acbe22f8484b4b5ff66a7499717fe1a9cc8"
uuid = "c87230d0-a227-11e9-1b43-d7ebe4e7570a"
version = "0.4.1"

[[FFMPEG_jll]]
deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "LAME_jll", "Libdl", "Ogg_jll", "OpenSSL_jll", "Opus_jll", "Pkg", "Zlib_jll", "libass_jll", "libfdk_aac_jll", "libvorbis_jll", "x264_jll", "x265_jll"]
git-tree-sha1 = "d8a578692e3077ac998b50c0217dfd67f21d1e5f"
uuid = "b22a6f82-2f65-5046-a5b2-351ab43fb4e5"
version = "4.4.0+0"

[[FileWatching]]
uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"

[[FixedPointNumbers]]
deps = ["Statistics"]
git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc"
uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93"
version = "0.8.4"

[[Fontconfig_jll]]
deps = ["Artifacts", "Bzip2_jll", "Expat_jll", "FreeType2_jll", "JLLWrappers", "Libdl", "Libuuid_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "21efd19106a55620a188615da6d3d06cd7f6ee03"
uuid = "a3f928ae-7b40-5064-980b-68af3947d34b"
version = "2.13.93+0"

[[Formatting]]
deps = ["Printf"]
git-tree-sha1 = "8339d61043228fdd3eb658d86c926cb282ae72a8"
uuid = "59287772-0a20-5a39-b81b-1366585eb4c0"
version = "0.4.2"

[[FreeType2_jll]]
deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "87eb71354d8ec1a96d4a7636bd57a7347dde3ef9"
uuid = "d7e528f0-a631-5988-bf34-fe36492bcfd7"
version = "2.10.4+0"

[[FriBidi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "aa31987c2ba8704e23c6c8ba8a4f769d5d7e4f91"
uuid = "559328eb-81f9-559d-9380-de523a88c83c"
version = "1.0.10+0"

[[FunctionalCollections]]
deps = ["Test"]
git-tree-sha1 = "04cb9cfaa6ba5311973994fe3496ddec19b6292a"
uuid = "de31a74c-ac4f-5751-b3fd-e18cd04993ca"
version = "0.5.0"

[[GLFW_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libglvnd_jll", "Pkg", "Xorg_libXcursor_jll", "Xorg_libXi_jll", "Xorg_libXinerama_jll", "Xorg_libXrandr_jll"]
git-tree-sha1 = "dba1e8614e98949abfa60480b13653813d8f0157"
uuid = "0656b61e-2033-5cc2-a64a-77c0f6c09b89"
version = "3.3.5+0"

[[GR]]
deps = ["Base64", "DelimitedFiles", "GR_jll", "HTTP", "JSON", "Libdl", "LinearAlgebra", "Pkg", "Printf", "Random", "Serialization", "Sockets", "Test", "UUIDs"]
git-tree-sha1 = "c2178cfbc0a5a552e16d097fae508f2024de61a3"
uuid = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71"
version = "0.59.0"

[[GR_jll]]
deps = ["Artifacts", "Bzip2_jll", "Cairo_jll", "FFMPEG_jll", "Fontconfig_jll", "GLFW_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pixman_jll", "Pkg", "Qt5Base_jll", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "ef49a187604f865f4708c90e3f431890724e9012"
uuid = "d2c73de3-f751-5644-a686-071e5b155ba9"
version = "0.59.0+0"

[[GeometryBasics]]
deps = ["EarCut_jll", "IterTools", "LinearAlgebra", "StaticArrays", "StructArrays", "Tables"]
git-tree-sha1 = "58bcdf5ebc057b085e58d95c138725628dd7453c"
uuid = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
version = "0.4.1"

[[Gettext_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "XML2_jll"]
git-tree-sha1 = "9b02998aba7bf074d14de89f9d37ca24a1a0b046"
uuid = "78b55507-aeef-58d4-861c-77aaff3498b1"
version = "0.21.0+0"

[[Glib_jll]]
deps = ["Artifacts", "Gettext_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Libiconv_jll", "Libmount_jll", "PCRE_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "7bf67e9a481712b3dbe9cb3dac852dc4b1162e02"
uuid = "7746bdde-850d-59dc-9ae8-88ece973131d"
version = "2.68.3+0"

[[Graphite2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "344bf40dcab1073aca04aa0df4fb092f920e4011"
uuid = "3b182d85-2403-5c21-9c21-1e1f0cc25472"
version = "1.3.14+0"

[[Grisu]]
git-tree-sha1 = "53bb909d1151e57e2484c3d1b53e19552b887fb2"
uuid = "42e2da0e-8278-4e71-bc24-59509adca0fe"
version = "1.0.2"

[[HTTP]]
deps = ["Base64", "Dates", "IniFile", "Logging", "MbedTLS", "NetworkOptions", "Sockets", "URIs"]
git-tree-sha1 = "14eece7a3308b4d8be910e265c724a6ba51a9798"
uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3"
version = "0.9.16"

[[HarfBuzz_jll]]
deps = ["Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "Graphite2_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg"]
git-tree-sha1 = "8a954fed8ac097d5be04921d595f741115c1b2ad"
uuid = "2e76f6c2-a576-52d4-95c1-20adfe4de566"
version = "2.8.1+0"

[[Hiccup]]
deps = ["MacroTools", "Test"]
git-tree-sha1 = "6187bb2d5fcbb2007c39e7ac53308b0d371124bd"
uuid = "9fb69e20-1954-56bb-a84f-559cc56a8ff7"
version = "0.2.2"

[[IniFile]]
deps = ["Test"]
git-tree-sha1 = "098e4d2c533924c921f9f9847274f2ad89e018b8"
uuid = "83e8ac13-25f8-5344-8a64-a9f2b223428f"
version = "0.5.0"

[[InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"

[[IrrationalConstants]]
git-tree-sha1 = "f76424439413893a832026ca355fe273e93bce94"
uuid = "92d709cd-6900-40b7-9082-c6be49f344b6"
version = "0.1.0"

[[IterTools]]
git-tree-sha1 = "05110a2ab1fc5f932622ffea2a003221f4782c18"
uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e"
version = "1.3.0"

[[IteratorInterfaceExtensions]]
git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856"
uuid = "82899510-4779-5014-852e-03e436cf321d"
version = "1.0.0"

[[JLLWrappers]]
deps = ["Preferences"]
git-tree-sha1 = "642a199af8b68253517b80bd3bfd17eb4e84df6e"
uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210"
version = "1.3.0"

[[JSExpr]]
deps = ["JSON", "MacroTools", "Observables", "WebIO"]
git-tree-sha1 = "bd6c034156b1e7295450a219c4340e32e50b08b1"
uuid = "97c1335a-c9c5-57fe-bc5d-ec35cebe8660"
version = "0.5.3"

[[JSON]]
deps = ["Dates", "Mmap", "Parsers", "Unicode"]
git-tree-sha1 = "8076680b162ada2a031f707ac7b4953e30667a37"
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
version = "0.21.2"

[[JpegTurbo_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "d735490ac75c5cb9f1b00d8b5509c11984dc6943"
uuid = "aacddb02-875f-59d6-b918-886e6ef4fbf8"
version = "2.1.0+0"

[[Kaleido_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "2ef87eeaa28713cb010f9fb0be288b6c1a4ecd53"
uuid = "f7e6163d-2fa5-5f23-b69c-1db539e41963"
version = "0.1.0+0"

[[LAME_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "f6250b16881adf048549549fba48b1161acdac8c"
uuid = "c1c5ebd0-6772-5130-a774-d5fcae4a789d"
version = "3.100.1+0"

[[LZO_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "e5b909bcf985c5e2605737d2ce278ed791b89be6"
uuid = "dd4b983a-f0e5-5f8d-a1b7-129d4a5fb1ac"
version = "2.10.1+0"

[[LaTeXStrings]]
git-tree-sha1 = "c7f1c695e06c01b95a67f0cd1d34994f3e7db104"
uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
version = "1.2.1"

[[Latexify]]
deps = ["Formatting", "InteractiveUtils", "LaTeXStrings", "MacroTools", "Markdown", "Printf", "Requires"]
git-tree-sha1 = "a4b12a1bd2ebade87891ab7e36fdbce582301a92"
uuid = "23fbe1c1-3f47-55db-b15f-69d7ec21a316"
version = "0.15.6"

[[Lazy]]
deps = ["MacroTools"]
git-tree-sha1 = "1370f8202dac30758f3c345f9909b97f53d87d3f"
uuid = "50d2b5c4-7a5e-59d5-8109-a42b560f39c0"
version = "0.15.1"

[[LibCURL]]
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"

[[LibCURL_jll]]
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"

[[LibGit2]]
deps = ["Base64", "NetworkOptions", "Printf", "SHA"]
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"

[[LibSSH2_jll]]
deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"

[[Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"

[[Libffi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "761a393aeccd6aa92ec3515e428c26bf99575b3b"
uuid = "e9f186c6-92d2-5b65-8a66-fee21dc1b490"
version = "3.2.2+0"

[[Libgcrypt_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgpg_error_jll", "Pkg"]
git-tree-sha1 = "64613c82a59c120435c067c2b809fc61cf5166ae"
uuid = "d4300ac3-e22c-5743-9152-c294e39db1e4"
version = "1.8.7+0"

[[Libglvnd_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll", "Xorg_libXext_jll"]
git-tree-sha1 = "7739f837d6447403596a75d19ed01fd08d6f56bf"
uuid = "7e76a0d4-f3c7-5321-8279-8d96eeed0f29"
version = "1.3.0+3"

[[Libgpg_error_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "c333716e46366857753e273ce6a69ee0945a6db9"
uuid = "7add5ba3-2f88-524e-9cd5-f83b8a55f7b8"
version = "1.42.0+0"

[[Libiconv_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "42b62845d70a619f063a7da093d995ec8e15e778"
uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531"
version = "1.16.1+1"

[[Libmount_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "9c30530bf0effd46e15e0fdcf2b8636e78cbbd73"
uuid = "4b2f31a3-9ecc-558c-b454-b3730dcb73e9"
version = "2.35.0+0"

[[Libtiff_jll]]
deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Pkg", "Zlib_jll", "Zstd_jll"]
git-tree-sha1 = "340e257aada13f95f98ee352d316c3bed37c8ab9"
uuid = "89763e89-9b03-5906-acba-b20f662cd828"
version = "4.3.0+0"

[[Libuuid_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "7f3efec06033682db852f8b3bc3c1d2b0a0ab066"
uuid = "38a345b3-de98-5d2b-a5d3-14cd9215e700"
version = "2.36.0+0"

[[LinearAlgebra]]
deps = ["Libdl"]
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[[LogExpFunctions]]
deps = ["ChainRulesCore", "DocStringExtensions", "IrrationalConstants", "LinearAlgebra"]
git-tree-sha1 = "34dc30f868e368f8a17b728a1238f3fcda43931a"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.3.3"

[[Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"

[[MacroTools]]
deps = ["Markdown", "Random"]
git-tree-sha1 = "5a5bc6bf062f0f95e62d0fe0a2d99699fed82dd9"
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
version = "0.5.8"

[[Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"

[[MbedTLS]]
deps = ["Dates", "MbedTLS_jll", "Random", "Sockets"]
git-tree-sha1 = "1c38e51c3d08ef2278062ebceade0e46cefc96fe"
uuid = "739be429-bea8-5141-9913-cc70e7f3736d"
version = "1.0.3"

[[MbedTLS_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"

[[Measures]]
git-tree-sha1 = "e498ddeee6f9fdb4551ce855a46f54dbd900245f"
uuid = "442fdcdd-2543-5da2-b0f3-8c86c306513e"
version = "0.3.1"

[[Missings]]
deps = ["DataAPI"]
git-tree-sha1 = "bf210ce90b6c9eed32d25dbcae1ebc565df2687f"
uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
version = "1.0.2"

[[Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"

[[MozillaCACerts_jll]]
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"

[[Mustache]]
deps = ["Printf", "Tables"]
git-tree-sha1 = "36995ef0d532fe08119d70b2365b7b03d4e00f48"
uuid = "ffc61752-8dc7-55ee-8c37-f3e9cdd09e70"
version = "1.0.10"

[[Mux]]
deps = ["AssetRegistry", "Base64", "HTTP", "Hiccup", "Pkg", "Sockets", "WebSockets"]
git-tree-sha1 = "82dfb2cead9895e10ee1b0ca37a01088456c4364"
uuid = "a975b10e-0019-58db-a62f-e48ff68538c9"
version = "0.7.6"

[[NaNMath]]
git-tree-sha1 = "bfe47e760d60b82b66b61d2d44128b62e3a369fb"
uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
version = "0.3.5"

[[NetworkOptions]]
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"

[[Observables]]
git-tree-sha1 = "fe29afdef3d0c4a8286128d4e45cc50621b1e43d"
uuid = "510215fc-4207-5dde-b226-833fc4488ee2"
version = "0.4.0"

[[Ogg_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "7937eda4681660b4d6aeeecc2f7e1c81c8ee4e2f"
uuid = "e7412a2a-1a6e-54c0-be00-318e2571c051"
version = "1.3.5+0"

[[OpenLibm_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "05823500-19ac-5b8b-9628-191a04bc5112"

[[OpenSSL_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "15003dcb7d8db3c6c857fda14891a539a8f2705a"
uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95"
version = "1.1.10+0"

[[OpenSpecFun_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1"
uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e"
version = "0.5.5+0"

[[Opus_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "51a08fb14ec28da2ec7a927c4337e4332c2a4720"
uuid = "91d4177d-7536-5919-b921-800302f37372"
version = "1.3.2+0"

[[OrderedCollections]]
git-tree-sha1 = "85f8e6578bf1f9ee0d11e7bb1b1456435479d47c"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.4.1"

[[PCRE_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b2a7af664e098055a7529ad1a900ded962bca488"
uuid = "2f80f16e-611a-54ab-bc61-aa92de5b98fc"
version = "8.44.0+0"

[[Parameters]]
deps = ["OrderedCollections", "UnPack"]
git-tree-sha1 = "34c0e9ad262e5f7fc75b10a9952ca7692cfc5fbe"
uuid = "d96e819e-fc66-5662-9728-84c9c7592b0a"
version = "0.12.3"

[[Parsers]]
deps = ["Dates"]
git-tree-sha1 = "9d8c00ef7a8d110787ff6f170579846f776133a9"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.0.4"

[[Pidfile]]
deps = ["FileWatching", "Test"]
git-tree-sha1 = "1be8660b2064893cd2dae4bd004b589278e4440d"
uuid = "fa939f87-e72e-5be4-a000-7fc836dbe307"
version = "1.2.0"

[[Pixman_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b4f5d02549a10e20780a24fce72bea96b6329e29"
uuid = "30392449-352a-5448-841d-b1acce4e97dc"
version = "0.40.1+0"

[[Pkg]]
deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"

[[PlotThemes]]
deps = ["PlotUtils", "Requires", "Statistics"]
git-tree-sha1 = "a3a964ce9dc7898193536002a6dd892b1b5a6f1d"
uuid = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a"
version = "2.0.1"

[[PlotUtils]]
deps = ["ColorSchemes", "Colors", "Dates", "Printf", "Random", "Reexport", "Statistics"]
git-tree-sha1 = "2537ed3c0ed5e03896927187f5f2ee6a4ab342db"
uuid = "995b91a9-d308-5afd-9ec6-746e21dbc043"
version = "1.0.14"

[[PlotlyBase]]
deps = ["ColorSchemes", "Dates", "DelimitedFiles", "DocStringExtensions", "JSON", "LaTeXStrings", "Logging", "Parameters", "Pkg", "REPL", "Requires", "Statistics", "UUIDs"]
git-tree-sha1 = "180d744848ba316a3d0fdf4dbd34b77c7242963a"
uuid = "a03496cd-edff-5a9b-9e67-9cda94a718b5"
version = "0.8.18"

[[PlotlyJS]]
deps = ["Base64", "Blink", "DelimitedFiles", "JSExpr", "JSON", "Kaleido_jll", "Markdown", "Pkg", "PlotlyBase", "REPL", "Reexport", "Requires", "WebIO"]
git-tree-sha1 = "ec6bc7270269be2d565b272116ca74ca2f8bd9ab"
uuid = "f0f68f2c-4968-5e81-91da-67840de0976a"
version = "0.18.7"

[[Plots]]
deps = ["Base64", "Contour", "Dates", "Downloads", "FFMPEG", "FixedPointNumbers", "GR", "GeometryBasics", "JSON", "Latexify", "LinearAlgebra", "Measures", "NaNMath", "PlotThemes", "PlotUtils", "Printf", "REPL", "Random", "RecipesBase", "RecipesPipeline", "Reexport", "Requires", "Scratch", "Showoff", "SparseArrays", "Statistics", "StatsBase", "UUIDs"]
git-tree-sha1 = "cfbd033def161db9494f86c5d18fbf874e09e514"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
version = "1.22.3"

[[Preferences]]
deps = ["TOML"]
git-tree-sha1 = "00cfd92944ca9c760982747e9a1d0d5d86ab1e5a"
uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.2.2"

[[Printf]]
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"

[[PyCall]]
deps = ["Conda", "Dates", "Libdl", "LinearAlgebra", "MacroTools", "Serialization", "VersionParsing"]
git-tree-sha1 = "169bb8ea6b1b143c5cf57df6d34d022a7b60c6db"
uuid = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0"
version = "1.92.3"

[[Qt5Base_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Fontconfig_jll", "Glib_jll", "JLLWrappers", "Libdl", "Libglvnd_jll", "OpenSSL_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libxcb_jll", "Xorg_xcb_util_image_jll", "Xorg_xcb_util_keysyms_jll", "Xorg_xcb_util_renderutil_jll", "Xorg_xcb_util_wm_jll", "Zlib_jll", "xkbcommon_jll"]
git-tree-sha1 = "ad368663a5e20dbb8d6dc2fddeefe4dae0781ae8"
uuid = "ea2cea3b-5b76-57ae-a6ef-0a8af62496e1"
version = "5.15.3+0"

[[REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"

[[Random]]
deps = ["Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[[RecipesBase]]
git-tree-sha1 = "44a75aa7a527910ee3d1751d1f0e4148698add9e"
uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
version = "1.1.2"

[[RecipesPipeline]]
deps = ["Dates", "NaNMath", "PlotUtils", "RecipesBase"]
git-tree-sha1 = "7ad0dfa8d03b7bcf8c597f59f5292801730c55b8"
uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c"
version = "0.4.1"

[[Reexport]]
git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b"
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
version = "1.2.2"

[[Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "4036a3bd08ac7e968e27c203d45f5fff15020621"
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
version = "1.1.3"

[[SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"

[[Scratch]]
deps = ["Dates"]
git-tree-sha1 = "0b4b7f1393cff97c33891da2a0bf69c6ed241fda"
uuid = "6c6a2e73-6563-6170-7368-637461726353"
version = "1.1.0"

[[Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"

[[SharedArrays]]
deps = ["Distributed", "Mmap", "Random", "Serialization"]
uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383"

[[Showoff]]
deps = ["Dates", "Grisu"]
git-tree-sha1 = "91eddf657aca81df9ae6ceb20b959ae5653ad1de"
uuid = "992d4aef-0814-514b-bc4d-f2e9a6c4116f"
version = "1.0.3"

[[Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"

[[SortingAlgorithms]]
deps = ["DataStructures"]
git-tree-sha1 = "b3363d7460f7d098ca0912c69b082f75625d7508"
uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c"
version = "1.0.1"

[[SparseArrays]]
deps = ["LinearAlgebra", "Random"]
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[[SpecialFunctions]]
deps = ["ChainRulesCore", "IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"]
git-tree-sha1 = "793793f1df98e3d7d554b65a107e9c9a6399a6ed"
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
version = "1.7.0"

[[StaticArrays]]
deps = ["LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "3240808c6d463ac46f1c1cd7638375cd22abbccb"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "1.2.12"

[[Statistics]]
deps = ["LinearAlgebra", "SparseArrays"]
uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[[StatsAPI]]
git-tree-sha1 = "1958272568dc176a1d881acb797beb909c785510"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.0.0"

[[StatsBase]]
deps = ["DataAPI", "DataStructures", "LinearAlgebra", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"]
git-tree-sha1 = "8cbbc098554648c84f79a463c9ff0fd277144b6c"
uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
version = "0.33.10"

[[StructArrays]]
deps = ["Adapt", "DataAPI", "StaticArrays", "Tables"]
git-tree-sha1 = "2ce41e0d042c60ecd131e9fb7154a3bfadbf50d3"
uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
version = "0.6.3"

[[SymPy]]
deps = ["CommonEq", "CommonSolve", "LinearAlgebra", "Markdown", "PyCall", "RecipesBase", "SpecialFunctions"]
git-tree-sha1 = "1ef257ecbcab8058595a68ca36a6844b41babcbd"
uuid = "24249f21-da20-56a4-8eb1-6a02cf4ae2e6"
version = "1.0.52"

[[TOML]]
deps = ["Dates"]
uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"

[[TableTraits]]
deps = ["IteratorInterfaceExtensions"]
git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39"
uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
version = "1.0.1"

[[Tables]]
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "TableTraits", "Test"]
git-tree-sha1 = "1162ce4a6c4b7e31e0e6b14486a6986951c73be9"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.5.2"

[[Tar]]
deps = ["ArgTools", "SHA"]
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"

[[Test]]
deps = ["InteractiveUtils", "Logging", "Random", "Serialization"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[[URIParser]]
deps = ["Unicode"]
git-tree-sha1 = "53a9f49546b8d2dd2e688d216421d050c9a31d0d"
uuid = "30578b45-9adc-5946-b283-645ec420af67"
version = "0.4.1"

[[URIs]]
git-tree-sha1 = "97bbe755a53fe859669cd907f2d96aee8d2c1355"
uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4"
version = "1.3.0"

[[UUIDs]]
deps = ["Random", "SHA"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[[UnPack]]
git-tree-sha1 = "387c1f73762231e86e0c9c5443ce3b4a0a9a0c2b"
uuid = "3a884ed6-31ef-47d7-9d2a-63182c4928ed"
version = "1.0.2"

[[Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"

[[VersionParsing]]
git-tree-sha1 = "80229be1f670524750d905f8fc8148e5a8c4537f"
uuid = "81def892-9a0e-5fdd-b105-ffc91e053289"
version = "1.2.0"

[[Wayland_jll]]
deps = ["Artifacts", "Expat_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg", "XML2_jll"]
git-tree-sha1 = "3e61f0b86f90dacb0bc0e73a0c5a83f6a8636e23"
uuid = "a2964d1f-97da-50d4-b82a-358c7fce9d89"
version = "1.19.0+0"

[[Wayland_protocols_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Wayland_jll"]
git-tree-sha1 = "2839f1c1296940218e35df0bbb220f2a79686670"
uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91"
version = "1.18.0+4"

[[WebIO]]
deps = ["AssetRegistry", "Base64", "Distributed", "FunctionalCollections", "JSON", "Logging", "Observables", "Pkg", "Random", "Requires", "Sockets", "UUIDs", "WebSockets", "Widgets"]
git-tree-sha1 = "5fe32e4086d49f7ab9b087296742859f3ae6d62a"
uuid = "0f1e0344-ec1d-5b48-a673-e5cf874b6c29"
version = "0.8.16"

[[WebSockets]]
deps = ["Base64", "Dates", "HTTP", "Logging", "Sockets"]
git-tree-sha1 = "f91a602e25fe6b89afc93cf02a4ae18ee9384ce3"
uuid = "104b5d7c-a370-577a-8038-80a2059c5097"
version = "1.5.9"

[[Widgets]]
deps = ["Colors", "Dates", "Observables", "OrderedCollections"]
git-tree-sha1 = "80661f59d28714632132c73779f8becc19a113f2"
uuid = "cc8bc4a8-27d6-5769-a93b-9d913e69aa62"
version = "0.6.4"

[[XML2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "1acf5bdf07aa0907e0a37d3718bb88d4b687b74a"
uuid = "02c8fc9c-b97f-50b9-bbe4-9be30ff0a78a"
version = "2.9.12+0"

[[XSLT_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgcrypt_jll", "Libgpg_error_jll", "Libiconv_jll", "Pkg", "XML2_jll", "Zlib_jll"]
git-tree-sha1 = "91844873c4085240b95e795f692c4cec4d805f8a"
uuid = "aed1982a-8fda-507f-9586-7b0439959a61"
version = "1.1.34+0"

[[Xorg_libX11_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll", "Xorg_xtrans_jll"]
git-tree-sha1 = "5be649d550f3f4b95308bf0183b82e2582876527"
uuid = "4f6342f7-b3d2-589e-9d20-edeb45f2b2bc"
version = "1.6.9+4"

[[Xorg_libXau_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4e490d5c960c314f33885790ed410ff3a94ce67e"
uuid = "0c0b7dd1-d40b-584c-a123-a41640f87eec"
version = "1.0.9+4"

[[Xorg_libXcursor_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXfixes_jll", "Xorg_libXrender_jll"]
git-tree-sha1 = "12e0eb3bc634fa2080c1c37fccf56f7c22989afd"
uuid = "935fb764-8cf2-53bf-bb30-45bb1f8bf724"
version = "1.2.0+4"

[[Xorg_libXdmcp_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4fe47bd2247248125c428978740e18a681372dd4"
uuid = "a3789734-cfe1-5b06-b2d0-1dd0d9d62d05"
version = "1.1.3+4"

[[Xorg_libXext_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "b7c0aa8c376b31e4852b360222848637f481f8c3"
uuid = "1082639a-0dae-5f34-9b06-72781eeb8cb3"
version = "1.3.4+4"

[[Xorg_libXfixes_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "0e0dc7431e7a0587559f9294aeec269471c991a4"
uuid = "d091e8ba-531a-589c-9de9-94069b037ed8"
version = "5.0.3+4"

[[Xorg_libXi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXfixes_jll"]
git-tree-sha1 = "89b52bc2160aadc84d707093930ef0bffa641246"
uuid = "a51aa0fd-4e3c-5386-b890-e753decda492"
version = "1.7.10+4"

[[Xorg_libXinerama_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll"]
git-tree-sha1 = "26be8b1c342929259317d8b9f7b53bf2bb73b123"
uuid = "d1454406-59df-5ea1-beac-c340f2130bc3"
version = "1.1.4+4"

[[Xorg_libXrandr_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll"]
git-tree-sha1 = "34cea83cb726fb58f325887bf0612c6b3fb17631"
uuid = "ec84b674-ba8e-5d96-8ba1-2a689ba10484"
version = "1.5.2+4"

[[Xorg_libXrender_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "19560f30fd49f4d4efbe7002a1037f8c43d43b96"
uuid = "ea2f1a96-1ddc-540d-b46f-429655e07cfa"
version = "0.9.10+4"

[[Xorg_libpthread_stubs_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "6783737e45d3c59a4a4c4091f5f88cdcf0908cbb"
uuid = "14d82f49-176c-5ed1-bb49-ad3f5cbd8c74"
version = "0.1.0+3"

[[Xorg_libxcb_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "XSLT_jll", "Xorg_libXau_jll", "Xorg_libXdmcp_jll", "Xorg_libpthread_stubs_jll"]
git-tree-sha1 = "daf17f441228e7a3833846cd048892861cff16d6"
uuid = "c7cfdc94-dc32-55de-ac96-5a1b8d977c5b"
version = "1.13.0+3"

[[Xorg_libxkbfile_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "926af861744212db0eb001d9e40b5d16292080b2"
uuid = "cc61e674-0454-545c-8b26-ed2c68acab7a"
version = "1.1.0+4"

[[Xorg_xcb_util_image_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "0fab0a40349ba1cba2c1da699243396ff8e94b97"
uuid = "12413925-8142-5f55-bb0e-6d7ca50bb09b"
version = "0.4.0+1"

[[Xorg_xcb_util_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll"]
git-tree-sha1 = "e7fd7b2881fa2eaa72717420894d3938177862d1"
uuid = "2def613f-5ad1-5310-b15b-b15d46f528f5"
version = "0.4.0+1"

[[Xorg_xcb_util_keysyms_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "d1151e2c45a544f32441a567d1690e701ec89b00"
uuid = "975044d2-76e6-5fbe-bf08-97ce7c6574c7"
version = "0.4.0+1"

[[Xorg_xcb_util_renderutil_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "dfd7a8f38d4613b6a575253b3174dd991ca6183e"
uuid = "0d47668e-0667-5a69-a72c-f761630bfb7e"
version = "0.3.9+1"

[[Xorg_xcb_util_wm_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "e78d10aab01a4a154142c5006ed44fd9e8e31b67"
uuid = "c22f9ab0-d5fe-5066-847c-f4bb1cd4e361"
version = "0.4.1+1"

[[Xorg_xkbcomp_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxkbfile_jll"]
git-tree-sha1 = "4bcbf660f6c2e714f87e960a171b119d06ee163b"
uuid = "35661453-b289-5fab-8a00-3d9160c6a3a4"
version = "1.4.2+4"

[[Xorg_xkeyboard_config_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xkbcomp_jll"]
git-tree-sha1 = "5c8424f8a67c3f2209646d4425f3d415fee5931d"
uuid = "33bec58e-1273-512f-9401-5d533626f822"
version = "2.27.0+4"

[[Xorg_xtrans_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "79c31e7844f6ecf779705fbc12146eb190b7d845"
uuid = "c5fb5394-a638-5e4d-96e5-b29de1b5cf10"
version = "1.4.0+3"

[[Zlib_jll]]
deps = ["Libdl"]
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"

[[Zstd_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "cc4bf3fdde8b7e3e9fa0351bdeedba1cf3b7f6e6"
uuid = "3161d3a3-bdf6-5164-811a-617609db77b4"
version = "1.5.0+0"

[[libass_jll]]
deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "HarfBuzz_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "5982a94fcba20f02f42ace44b9894ee2b140fe47"
uuid = "0ac62f75-1d6f-5e53-bd7c-93b484bb37c0"
version = "0.15.1+0"

[[libfdk_aac_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "daacc84a041563f965be61859a36e17c4e4fcd55"
uuid = "f638f0a6-7fb0-5443-88ba-1cc74229b280"
version = "2.0.2+0"

[[libpng_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "94d180a6d2b5e55e447e2d27a29ed04fe79eb30c"
uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f"
version = "1.6.38+0"

[[libvorbis_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Ogg_jll", "Pkg"]
git-tree-sha1 = "c45f4e40e7aafe9d086379e5578947ec8b95a8fb"
uuid = "f27f6e37-5d2b-51aa-960f-b287f2bc3b7a"
version = "1.3.7+0"

[[nghttp2_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"

[[p7zip_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"

[[x264_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4fea590b89e6ec504593146bf8b988b2c00922b2"
uuid = "1270edf5-f2f9-52d2-97e9-ab00b5d0237a"
version = "2021.5.5+0"

[[x265_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "ee567a171cce03570d77ad3a43e90218e38937a9"
uuid = "dfaa095f-4041-5dcd-9319-2fabd8486b76"
version = "3.5.0+0"

[[xkbcommon_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Wayland_jll", "Wayland_protocols_jll", "Xorg_libxcb_jll", "Xorg_xkeyboard_config_jll"]
git-tree-sha1 = "ece2350174195bb31de1a63bea3a41ae1aa593b6"
uuid = "d8fb68d0-12a3-5cfd-a85a-d49703b185fd"
version = "0.9.1+5"
"""

# ╔═╡ Cell order:
# ╠═e8595a60-222f-11ec-0595-c9717ac06507
# ╟─431922d9-e97a-4300-a482-2d458b66c67a
# ╟─85cf0b95-4446-4e84-a6c3-f9d3fcf4cd61
# ╟─53b8d020-b4a9-4c74-b0cc-dba03b6edbd3
# ╟─4257606e-3eff-4124-aad3-517998f97d24
# ╠═61b1bf99-507b-4379-b537-86ce040f1418
# ╟─d17a8914-6ecf-4606-a664-7242d0f8f06c
# ╠═2056778d-12f0-4325-920f-f6c7e453918b
# ╟─4f6feaf8-5322-4afc-b31d-211761e222c2
# ╟─f676a35a-c61e-4547-b176-211dd3dc647b
# ╟─d8e3eda0-cada-4047-81cc-137a54e1b5e6
# ╟─897cfd67-1be7-40e4-87d9-c11bc9de55d4
# ╟─67e7f9f5-6e78-4579-97f7-7c0349b39afd
# ╟─4d6550b8-4e9d-4437-84bd-d978e33bfdb8
# ╠═997c5ff7-ac5d-484f-bcdf-a89194d112ee
# ╟─19f1f8b8-0f5c-4388-b550-f4cdd7619311
# ╠═8e1588d8-1d7a-4151-b8a1-afc3c1298887
# ╟─09baa7ce-fc86-42a5-8130-3c8125c93f5b
# ╠═653aa355-0c9d-4520-befd-d3f91678ffaa
# ╟─1938fc99-5366-4bc0-a2b3-892d7281db93
# ╠═0f723758-c34e-4a3b-ad72-853cc23b29fc
# ╠═253ae086-b3b0-4243-b05d-4e575166aa53
# ╟─9003d85b-eaf0-44f9-b2b7-1dd990e4fd76
# ╟─c18c2f4b-1e5f-463f-8464-0a6387896efc
# ╠═0f3486cc-8de9-452c-a0a1-b8c5277c1592
# ╠═f4ee2c3e-7a1b-4d4a-99cf-0dda3ae572d7
# ╠═cf0c4904-6b99-4af7-8aee-d03593bc2091
# ╠═e86f3da1-ab64-4582-9fc7-8f12966c318f
# ╟─84f78af9-2866-404e-a121-3e3c6afe617b
# ╠═9bf041fa-c284-4425-831c-2d8a207e54e2
# ╠═512fadab-9352-4d45-b73e-d754b30114e4
# ╟─6612a222-06c1-47a8-b024-146ca8caea08
# ╠═604e2572-57d6-4076-b4bc-35adcceb7994
# ╟─ef868e86-0a6a-47fb-b2a5-d9190cd03c0a
# ╟─74bf0f00-bc45-4d26-9c61-f164de3d21e0
# ╟─50432a00-fdbe-448e-a6c1-89b1d01d435d
# ╟─4bf801a5-b443-46d1-a110-ab8096527116
# ╠═2136e05b-bef2-4dc8-8723-3fbb8360cba0
# ╟─5532b807-94e2-4ff2-9b65-41d1423863c6
# ╠═904d25d1-2244-4f76-ac1c-b1fef76ff41a
# ╟─2ba19d1c-f22e-47c8-b81c-979e0edd7348
# ╠═9eeb302c-a277-437d-9e95-345b72d1a3a4
# ╟─15949e72-93cf-4aa6-8524-5b55fe9eb229
# ╟─6935e6f6-e926-4766-89a4-8d86408cc15d
# ╟─aed97c10-bcae-4552-b522-afb0a6073c7a
# ╟─760596e6-3937-4024-b3b4-7bfae97c4a4f
# ╟─64d47104-23e7-492c-aa5e-c6eee7f6d10d
# ╟─ff31fe54-2f96-4e12-bf62-395dd29fa515
# ╟─6867d0da-516e-4924-b3f3-be7bbe75d4fc
# ╟─9ca33e7d-aa40-4970-9072-bcf0f754ec04
# ╟─fe385398-3bd1-4662-8411-e2c9beda9a9f
# ╟─672d62df-7c33-4260-8c4f-a72e8a900bd3
# ╟─c389944d-1d91-44aa-a28d-d0848bb10228
# ╟─e7d5a0e0-0b6b-4012-88cd-7e50283fb721
# ╟─fc2349c9-fb1f-4ce3-94fc-adb98f3170b8
# ╠═30e16586-b504-4332-9f6c-cdeb3f9c686c
# ╟─2f8356bc-311a-4826-861e-4852ed01bca1
# ╟─45d7938f-a9ff-4a21-b0f8-74a7b69e1a3d
# ╠═af547106-640f-4d89-b96d-b1d625822697
# ╠═a2779834-7808-4bad-a97a-bc90dba2adc7
# ╟─d9ef00bd-1ac5-4406-9cb7-ae9d90d2387e
# ╠═76c7aed0-4bac-4a03-8a07-00583c571c52
# ╠═180d6fe0-baeb-4c05-bfc9-213a6f1ec07c
# ╟─a7da009c-b867-46d2-84a2-087287521aa8
# ╟─5522536b-a0df-41f8-8525-856923f49104
# ╠═337404a1-514b-4f40-9aa7-738d0c07d34f
# ╟─7dcb7519-f6cc-47b6-bbf2-1896a0053a85
# ╟─dd6b45de-fa40-4697-a372-d7f6a75bc704
# ╟─e052a4ad-90a0-4f7f-a1e7-a35b92270d74
# ╟─65dcc377-8278-4c08-867b-012065989b1f
# ╟─c2c157cb-29fa-488b-a5dd-caef9e392c6b
# ╟─1dd55ddd-2c09-4d8c-83d3-442ebcf0d579
# ╠═0bd81932-75a6-4b74-a264-bb16ae798a44
# ╠═c3ca6592-a758-40fc-96c5-e8609071697f
# ╠═279a2774-a565-4ffa-9577-b2e987abed37
# ╟─1dd28947-9fa2-42bc-9666-6e1b5e12a147
# ╠═2b0dc6fe-ae32-48c9-a400-ad5fb8fbef4e
# ╠═40420c6d-122b-454d-9954-8ec29765f3f2
# ╠═be180c4f-177b-41a7-83d3-5a0220c9ad0e
# ╠═067ffcf8-a398-4e50-bcf7-5425906f4a87
# ╠═a1ce3aac-6e19-4de0-bcd5-4e86b26aab71
# ╟─3cf6ffc2-0f08-41f7-adaa-9fa22f585881
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002

max_stars_repo_name: akielbowicz/cbc-algebra-ingenieria

max_issues_repo_name: akielbowicz/cbc-algebra-ingenieria

max_forks_repo_name: akielbowicz/cbc-algebra-ingenieria


text:
# -*- encoding: utf-8 -*-
#
# The MIT License (MIT)
#
# Copyright © 2021 Matteo Foglieni and Riccardo Gervasoni
#

# RBG print functions
print(io::IO, c::RGB{T}) where T = print(io, "RGB = (", c.r, ", ", c.g, ", ", c.b, ")" )
print(c::RGB{T}) where T = print(stdout, c)
println(io::IO, c::RGB{T}) where T = println(io, "RGB = (", c.r, ", ", c.g, ", ", c.b, ")" )
println(c::RGB{T}) where T = println(stdout, c)

# Point print functions
print(io::IO, p::Point) = print(io, "Point = (", p.x, ", ", p.y, ", ", p.z, ")" )
print(p::Point) = print(stdout, p)
println(io::IO, p::Point) = print(io, "Point = (", p.x, ", ", p.y, ", ", p.z, ")" )
println(p::Point) = println(stdout, p)

# Vec print functions
print(io::IO, v::Vec) = print(io, "Vec = (", v.x, ", ", v.y, ", ", v.z, ")" )
print(v::Vec) = print(stdout, v)
println(io::IO,v::Vec) = println(io, "Vec = (", v.x, ", ", v.y, ", ", v.z, ")" )
println(v::Vec) = println(stdout,v)

# Normal print functions
print(io::IO, n::Normal) = print(io, "Normal = (", n.x, ", ", n.y, ", ", n.z, ")" )
print(n::Normal) = print(stdout, n)
println(io::IO,n::Normal) = println(io, "Normal = (", n.x, ", ", n.y, ", ", n.z, ")" )
println(n::Normal) = println(stdout,n)

# Ray print functions
function println(io::IO, ray::Ray)
     println(io, "Ray with origin-direction-tmin-tmax-depth:")
     println(io, ray.origin, " \t  ", ray.dir)
     println(io, "tmin = ", ray.tmin, " \t tmax = ", ray.tmax, " \t depth = ", ray.depth)
end
function print(io::IO, ray::Ray)
     println(io, "Ray with origin-direction-tmin-tmax-depth:")
     println(io, ray.origin, " \t  ", ray.dir)
     println(io, "tmin = ", ray.tmin, " \t tmax = ", ray.tmax, " \t depth = ", ray.depth)
end
println(ray::Ray) = println(stdout, ray)
print(ray::Ray) = print(stdout, ray)

# Vec2d print functions
println(io::IO, uv::Vec2d) =  println(io, "Vec2d = (", uv.u, ", ", uv.v, ")" )
println(uv::Vec2d) =  println(stdout, "Vec2d = (", uv.u, ", ", uv.v, ")" )
print(io::IO, uv::Vec2d) =  print(io, "Vec2d = (", uv.u, ", ", uv.v, ")" )
print(uv::Vec2d) =  print(stdout, "Vec2d = (", uv.u, ", ", uv.v, ")" )

# HitRecord print functions
function println(io::IO, hit::HitRecord)
     println(io, "HitRecord with  the following criteria:")
     println(io, "world point :\t" , hit.world_point)
     println(io, "normal :\t" , hit.normal)
     println(io, "surface point :\t" , hit.surface_point)
     println(io, "t of hit :\t" , hit.t)
     println(io, "ray :\t" , hit.ray)
     println(io, "shape = ", typeof(hit.shape))
end
print(io::IO, hit::HitRecord) = println(io, hit)
println(hit::HitRecord) = println(stdout, hit)
print(hit::HitRecord) = print(stdout, hit)

# AABB print functions
function println(io::IO, aabb::AABB)
     println(io, "AABB with the following points:")
     println(io, "minimum point m :\t" , aabb.m)
     println(io, "maximum point M :\t" , aabb.M)
end
print(io::IO,  aabb::AABB) = println(io, aabb)
println(aabb::AABB) = println(stdout, aabb)
print(aabb::AABB) = print(stdout, aabb)

function println(img::HDRimage, n::Int64=5)
     n>=1 || throw(ArgumentError("not a valid index; $n must be >0"))
     n<=50 || throw(ArgumentError("too big index; $n must be <=50"))

     w=img.width
     h=img.height
     println("HDRImage to be printed")
     println("width = ", w, "\t height = ", h)
     if (w*h) <= (2*n)
          for c in img.rgb_m; println(c); end
     else
          for i in 1:n; println(img.rgb_m[n]);end
          println("...")
          for i in 1:n; println(img.rgb_m[end-n+i]);end
     end
     nothing
end

function print_not_black(img::HDRimage)
     w=img.width
     h=img.height
     println("HDRImage to be printed")
     println("width = ", w, "\t height = ", h)

     for (i, color) in enumerate(img.rgb_m)
          color==BLACK ? nothing : println(i, "\t", color)
     end

     nothing
end


text:
board = [[" ", " ", " "],
         [" ", " ", " "],
         [" ", " ", " "]]

player1 = "X"
player2 = "O"

player1_win = -1
tie = 0
player2_win = 1

function print_board(board)
    println("    1   2   3")
    println(" 1  ", join(board[1], " | "))
    println("   ———┼———┼———")
    println(" 2  ", join(board[2], " | "))
    println("   ———┼———┼———")
    println(" 3  ", join(board[3], " | "))
end

function check_available(board)
    available_cells = []
    for i in 1:3, j in 1:3
        if board[i][j] == " "
            push!(available_cells, (i, j))
        end
    end
    return available_cells
end

function check_win(board)

    # Rows
    for i in 1:3
        if (board[i][1] == board[i][2] == board[i][3]) && (board[i][1] in [player1, player2])
            if (board[i][1] == player1)
                return player1_win
            end
            return player2_win
        end
    end

    # Column
    for i in 1:3
        if (board[1][i] == board[2][i] == board[3][i]) && (board[1][i] in [player1, player2])
            if (board[1][i] == player1)
                return player1_win
            end
            return player2_win
        end
    end

    # Principal diagonal
    if (board[1][1] == board[2][2] == board[3][3]) && (board[1][1] in [player1, player2])
        if (board[1][1] == player1)
            return player1_win
        end
        return player2_win
    end

    # Other diag
    if (board[1][3] == board[2][2] == board[3][1]) && (board[1][3] in [player1, player2])
        if (board[1][3] == player1)
            return player1_win
        end
        return player2_win
    end

    # Tie
    if length(check_available(board)) == 0
        return tie
    end

    # No one wins, game still goes on
    return nothing
end

function make_move!(board, player, (x, y))
    board[x][y] = player
end

function worst_move(board)
    worst_score = Inf

    worst_pos = (0, 0)

    for i in 1:3, j in 1:3
        if board[i][j] == " "

            board[i][j] = player2

            score = minimax(board, 0, true)

            board[i][j] = " "

            if score < worst_score
                worst_score = score
                worst_pos = (i, j)
            end
        end
    end
    return worst_pos
end

function ai_move!(board, difficulty)
    if difficulty == "loser"
        make_move!(board, player2, worst_move(board))
    elseif difficulty == "easy"
        pos = rand(check_available(board))
        make_move!(board, player2, pos)
    elseif difficulty == "medium"
        if rand() < 0.3
            make_move!(board, player2, best_move(board))
        else
            pos = rand(check_available(board))
            make_move!(board, player2, pos)
        end
    elseif difficulty == "hard"
        if rand() < 0.7
            make_move!(board, player2, best_move(board))
        else
            pos = rand(check_available(board))
            make_move!(board, player2, pos)
        end
    elseif difficulty == "impossible"
        make_move!(board, player2, best_move(board))
    end

end

function minimax(board, depth, is_maximising)
    result = check_win(board)

    if result !== nothing
        return result
    elseif is_maximising

        best_score = -Inf

        for i in 1:3, j in 1:3
            if board[i][j] == " "

                board[i][j] = player2

                score = minimax(board, depth + 1, false)

                board[i][j] = " "

                best_score = max(score, best_score)
            end
        end

        return best_score
    else
        best_score = Inf

        for i in 1:3, j in 1:3
            if board[i][j] == " "

                board[i][j] = player1

                score = minimax(board, depth + 1, true)

                board[i][j] = " "

                best_score = min(score, best_score)
            end
        end

        return best_score
    end

end

function best_move(board)
    best_score = -Inf

    best_pos = (0, 0)

    for i in 1:3, j in 1:3
        if board[i][j] == " "

            board[i][j] = player2

            score = minimax(board, 0, false)

            board[i][j] = " "

            if score > best_score
                best_score = score
                best_pos = (i, j)
            end
        end
    end
    return best_pos
end

function move_input(board, prompt, params)

    print(prompt)
    txt = split(readline())

    if txt == ["exit"]
        exit()
    end

    if length(txt) == params && txt[1] in string.(collect(1:3)) && txt[2] in string.(collect(1:3)) && (board[parse(Int, txt[1])][parse(Int, txt[2])] == " ")
        return txt
    else
        println("Please enter a valid command (See README)")
        move_input(board, prompt, params)
    end
end

function generalised_input(prompt, same_line, choices, params)
    same_line ? print(prompt) : println(prompt)

    txt = split(lowercase(readline()))

    if txt == ["exit"]
        exit()
    end

    if length(txt) == params && txt[1] in choices
        return txt
    else
        println("Please enter a valid command (See README)")
        generalised_input(prompt, same_line, choices, params)
    end
end

function singleplayer(board, (player1, player2), (player1_win, player2_win, tie))
    diff_levels = """
    Choose a difficulty level:
    - `loser` - AI always makes worst move
    - `easy` - AI plays randomly
    - `medium` - AI makes some mistakes
    - `hard` - AI makes very few mistakes
    - `impossible` - AI always makes best move. Impossible to win.
    """

    println(diff_levels)
    difficulty = generalised_input("Difficulty: ", true, ["loser", "easy", "medium", "hard", "impossible"], 1)[1]

    println("Human is X, AI is O. Human goes first.")
    print_board(board)

    while true

        txt = move_input(board, "Enter position of cell (row and column seperated by space): ", 2)

        make_move!(board, player1, (parse(Int, txt[1]), parse(Int, txt[2])))

        if check_win(board) == player1_win
            println("Human wins! The humans are still worthy!")
            break
        elseif check_win(board) == player2_win
            println("AI wins. Humanity has no hope.")
            break
        elseif check_win(board) == tie
            println("Tie! Have we reached the singularity?")
            break
        end

        ai_move!(board, difficulty)
        print_board(board)

        if check_win(board) == player1_win
            println("Human wins! The human are still worthy!")
            break
        elseif check_win(board) == player2_win
            println("AI wins. Humanity has no hope.")
            break
        elseif check_win(board) == tie
            println("Tie! Have we reached the singularity?")
            break
        end
    end
end

function multiplayer(board, (player1, player2), (player1_win, player2_win, tie))
    println("Player 1 is X, Player 2 is O. Player 1 goes first.")
    print_board(board)

    while true

        txt = move_input(board, "Enter position of cell (row and column seperated by space): ", 2)

        make_move!(board, player1, (parse(Int, txt[1]), parse(Int, txt[2])))
        print_board(board)

        if check_win(board) == player1_win
            println("Player 1 Wins!")
            break
        elseif check_win(board) == player2_win
            println("Player 2 Wins!")
            break
        elseif check_win(board) == tie
            println("Tie!")
            break
        end

        txt = move_input(board, "Enter position of cell (row and column seperated by space): ", 2)

        make_move!(board, player2, (parse(Int, txt[1]), parse(Int, txt[2])))

        print_board(board)

        if check_win(board) == player1_win
            println("Player 1 Wins!")
            break
        elseif check_win(board) == player2_win
            println("Player 2 Wins!")
            break
        elseif check_win(board) == tie
            println("Tie!")
            break
        end
    end
end

function play_again()
    replay = generalised_input("Play again? (y/n): ", true, ["y", "n"], 1)[1]
    if replay == "y"
        run(`julia $PROGRAM_FILE`)
        exit()
    else
        exit()
    end
end

mode = generalised_input("Welcome to TicTacToe! Would you like to play singleplayer (1) or multiplayer (2)?", false, ["1", "2"], 1)[1]

if mode == "1"
    singleplayer(board, (player1, player2), (player1_win, player2_win, tie))
else
    multiplayer(board, (player1, player2), (player1_win, player2_win, tie))
end

play_again()

max_stars_repo_name: soumitradev/youtube-tutorial

max_issues_repo_name: soumitradev/youtube-tutorial

max_forks_repo_name: soumitradev/youtube-tutorial