text:
# propagators.jl
# Let's get those ψ moving.

"""
    SiteEnergyFromDipoles(dipoles,S,E)

Calculate site-energies for sites, from potential generated by dipoles at
other sites.

dipoles - dipole matrix (e*a_0)
S - previous site energies (Hartree)

returns:
S - Updated site energies for TightBinding Hamiltonian (Hartree)
"""
function SiteEnergyFromDipoles(dipoles,S,E)
    S = zeros(N)
    for i in 1:N
        S[i]+=-field_ext*(r*i)
        for j in 1:N
            if (j==i)
                # avoid infinity in self energies
                continue
            end
            # Contribution to site energy (1 e- at site) from dipoles
            S[i]+=sign(j-i)*dipoles[j]/(r*(i-j))^2
        end
    end
    S = S
    H = diagm(E,-1)+diagm(S)+diagm(E,1)
    return S,H
end

"""
    FieldFromDensity(density)

Calculate field at each dipole site from the charge density at every other site

density - electron density found from the wavefunction |Psi|^2

returns:
Field - electrostatic field
"""
function FieldFromDensity(density)
    field=zeros(N)
    for i in 1:N
        Fsum=zero(eltype(density)) # Calculate total field at each
        for j in 1:N
            if (j==i)
                continue # avoid infinite self energies
            end
            Fsum+=-sign(i-j)*density[j]/(i-j)^2 # How much do the dipoles respond to the electron density?
        end                         # check power of r for field from point charge.
        field[i]=Fsum/r^2
    end
    return field
end

"""
    FieldFromDipole(dipoles)

Calculate field at each dipole site from the induced dipole-induced dipole
interations at every other site

dipoles - existsing induced dipole

returns:
FieldDI - electrostatic field
"""
function FieldFromDipole(dipole)
    FieldDI=zeros(N)
    for i in 1:N
        FDIsum=zero(eltype(dipole)) # Calculate total field at each
        for j in 1:N
            if (j==i)
                continue # avoid infinite self energies
            end
            FDIsum+=-9*sign(j-i)*dipole[j]/((r*(j-i))^7) # How much do the dipoles respond to the electron density?
        end
        FieldDI[i]=FDIsum
    end
    return FieldDI
end

"""
    UpdateDipole(field, dipole, dampening, alpha)

Update dipole vector by solving the equation E = \alpha*p

field  - electrostatic field from electron density at every other site
dipole - current dipole vector to be updated
dampening - Contains the exponential decay of the dipole response (exp(-TimeStep*DecayRate))
alpha - polarisability of sites (assuming uniformity)

returns:
dipole - updates dipole moments induced by electrostatic fields
"""
function UpdateDipole(field, dipole, dampening, alpha=1.0)
    alphainv = 1*ones(N)/alpha#*dipolestrength
    # diagonal elements from polarisability of sites
    M = diagm(alphainv)
    n=0
    # Off-diagonal elements from separation between sites
    for i in 1:N
        for j in 1:N
            if (j==i)
                continue
            end
            M[n+j] = 1/(r*(j-i))^3
        end
        n+=N
    end
    new_dipole = \(M,field)
    # Update dipoles with a fraction from the new dipole matrix
    dipole += dampening*(new_dipole-dipole)
    return dipole
end

"Original JMF function; dipoles by exponential relaxation to t=+∞ solution."
function dipoles_by_relaxation(dipoles,density,dampening)
    for i in 1:N
        relaxeddipole=zero(eltype(density)) # fix type instability; initialise to zero in the supplied type of density
        for j in 1:N
            if (j==i)
                continue # avoid infinite self energies
            end
            relaxeddipole+=density[j]/(i-j)^1 # How much do the dipoles respond to the electron density?
        end

        dipoles[i]+=dampening*(relaxeddipole-dipoles[i]) # Approaches the infinite time limit via Zeno's dichotomy
    end
    return dipoles
end

"""
    AdiabaticPropagation(S,dipoles,E)

Build Hamiltonian from Dipoles (via SiteEnergyFromDipoles), diagonalise and
update dipoles responding to ground state electron density. A wrapper
function.

Time is ill-defined in this simulation - it takes you towards equilibrium.

S       - (Hartree)
dipoles -
E       - (Hartree)

returns
S       -
psi     -
Density -
dipoles -
"""
function AdiabaticPropagation(S,dipoles,density,E,dampening,verbose::Bool=true,dipole_int::Bool=false)
    S,H = SiteEnergyFromDipoles(dipoles,S,E)
    psi=eigvecs(H)[:,1] # gnd state

    if verbose
        println("Adiabtic State energy: <psi|H|psi> = ",psi'*H*psi)
        KE=diagm(E,-1)+diagm(E,+1)
        PE=diagm(S)
        println("KE: <psi|KE|psi> = ",psi'*KE*psi)
        println("PE: <psi|PE|psi> = ",psi'*PE*psi)
    end

    density=psi.^2
    Field=FieldFromDensity(density)+field_ext
    dipoles = UpdateDipole(Field, dipoles, dampening)

    if dipole_int
        FieldDI = FieldFromDipole(dipoles)
        dipoles = UpdateDipole(Field+FieldDI, dipoles, dampening)
    end

    return S,H,psi,density,dipoles
end

"""
    UnitaryPropagation(dipoles,S,E,psi,dt,dampening; slices::Int=1)

Self-consistent response of the lattice with unitary (time dependent)
evolution of the wavefunction.
"""
function UnitaryPropagation(dipoles,density,S,E,psi,dt,dampening; slices::Int=1)
    S,H=SiteEnergyFromDipoles(dipoles,S,E)

    H=diagm(E,-1)+diagm(S)+diagm(E,+1)

    En=eigvals(H)[1]
    println("First Eigval (adiabatic): ",En)

#    psi=eigvecs(H)[:,1] # gnd state; reproduces adiabtic state (eigval) above
    println("State energy: <psi|H|psi> = ",psi'*H*psi)
    KE=diagm(E,-1)+diagm(E,+1)
    PE=diagm(S)
    println("KE: <psi|KE|psi> = ",psi'*KE*psi)
    println("PE: <psi|PE|psi> = ",psi'*PE*psi)

    psi=TimeDependentPropagation(psi,H,dt,slices=slices,decompose=false,verbose=false)

    density=abs(psi.^2) # can be Complex!

    Field=FieldFromDensity(density)+field_ext
    dipoles = UpdateDipole(Field, dipoles, dipolestrength)

    return S,H,psi,density,dipoles
end

"""
    TimeDependentPropagation(psi,H,dt;slices::Int=1,decompose::Bool=false,verbose::Bool=false)

Propagate Wavefunction directly with Hamiltonian and time dependent Schrodinger equation.

Psi (N) is the wavefunction; H the Hamiltonian (NxN); dt the length of time to
propgate along; slices is how many slices to decompose the Unitary operator
into; verbose sets the display of info on the unitary nature of U, whether U*U'
~= I.

psi         - wavefunction
H           - TightBinding Hamiltonian (Hartree)
dt          - Time Step (0.02418884326505 fs)
slices      - sub-time step (0.02418884326505 fs)
decompose   - Perform Trotter Expansion (Boolean)
verbose     - Print unitary transformation (Boolean)

returns:
psi         - wavefunction
"""
function TimeDependentPropagation(psi,H,dt;slices::Int=1,decompose::Bool=false,verbose::Bool=false,test::Bool=false) # propagate directly using full Hamiltonian=T+V
    dt=dt/slices
    U=eye(H) # identiy matrix same size + type as H

    for i=1:slices
        if decompose
            S,J=Decompose_H(H) # split into diagonal and off-diag terms
            # Trotter decomposition
            U*=expm(-im*J*dt/2)*expm(-im*S*dt)*expm(-im*J*dt/2)
        else
            U*=expm(-im*H*dt)
        end
    end

    psi=U*psi # OK; we've built out unitary time evolution operator U, now apply it

    if verbose # for debugging / introspection
        @printf(" (matrix-squaring slices: %d) U: \n",slices)
        display(U)
        println("\n\tUU': (in any sane world this should be = Identity )\n")
        display(U*U') # Why you no unitary?

        println("\nPre normalised Norm of psi: ",norm(psi))
    end

    normalisation=sqrt(sum(abs.(psi.^2))) # Nb: for normalisation of WAVEFUNCTION; must SQUAREROOT the sum of density
    #println("Normalising Psi by dividing by: ",normalisation)
    psi=psi/normalisation # Normalise propagated wavefunction

    if test
        psi = [psi, U]
    end

    return psi
end

"""
    TimeDependentPropagation(psi,H,dt,E)

Propagate (in time) using eigenvalue

psi     - wavefunction
H       - TightBinding Hamiltonian (Hartree)
dt      - Time step (0.02418884326505 fs)
E       - Energy Eigenvalues (Hartree)

returns:
psi     - wavefunction
"""
function TimeDependentPropagation(psi,H,dt,E)
    psi=exp(-im*E*dt)*psi
    println("Pre normalised Norm of psi: ",norm(psi))
#    psi/=norm(psi*psi') # Normalise propagated wavefunction
    return psi
end


text:
struct State
  pc
  acc
end

macro acc(increment)
  return function(state) State(state.pc+1, state.acc+increment) end
end

macro nop(ignored)
  return function(state) State(state.pc+1, state.acc) end
end

macro jmp(offset)
  return function(state) State(state.pc+offset, state.acc) end
end

sourcecode = readlines("a8.txt")

function getprogram(tochange)
  program = []
  for (id,line) in enumerate(sourcecode)
    if id == tochange
      if startswith(line, "jmp")
        line = replace(line, "jmp"=>"nop")
      elseif startswith(line, "nop")
        line = replace(line, "nop"=>"jmp")
      end
    end
    push!(program, eval(Meta.parse("@" * line)))
  end
  program
end

function detectLoop(program)
  seen = BitSet()
  state = State(1,0)
  while state.pc <= length(program) && !in(state.pc, seen)
    push!(seen, state.pc)
    state = program[state.pc](state)
  end
  state
end

part1 = detectLoop(getprogram(0))
println("$(part1.acc)")

function findModification()
  for tochange in 1:length(sourcecode)
    state = detectLoop(getprogram(tochange))
    if state.pc > length(sourcecode)
      return state.acc
    end
  end
  nothing
end

part2 = findModification()
println("$part2")

ext: jl


text:
const initialObjValue = 1.529659701346959e-5
const objGap = 0.02*initialObjValue

const riskLowerBound = 1E-04

user_initial_guess = Float64[0.0008209427811086344 0.0007636835675518444 0.0005701047968333946 0.0008769116263480982 0.00041324527675481526 0.0005800434950967022 0.0007210045551505841 0.0006276031212332207 0.0007932877009665201 0.0008881171637927818 0.0008766018612865671 0.0006320318164184507 0.00046864233622053727 0.0007972152206997032 0.00044410020082646863 0.00048751053639709734 0.0006271324945815114 0.000833594526671095 0.000637517908021743 0.0005758235103795233 0.0008211858446615176 0.0005506595813249986 0.0004937790049517456 0.00030326690290466917 0.0007858265233236424 0.0004283766060798492 0.0007023563531744242 0.0006383812893485663 0.00041660529637406083 0.0008869414840670435 0.0008486309841526661 0.0007878373981276149 0.0007025895738211321 0.0006221266154370171 0.0007253224649432664 0.0007179847285153958 0.0005743155113023336 0.0004651830659334972 0.0006994539928083114 0.000813757012867089 0.0008426123267428326 0.0008129090919633393 0.0002224035375153371 0.0007633996283991556 0.0008060377452304927 0.0005805474993823768 0.0006758568767157172 0.0008487093317498039 0.0007273095454223649 0.0007672506824693867 0.00034776956635203585 0.000667823526204176 0.0008073333001026818 0.0008118463955352388 0.0008965575169526982 0.0004495653113838658 0.0006647997123165969 0.0006472528325401913 0.0009356519965734018 0.0010672497699516243 0.0011253462942174997 0.0006076383475545551 0.0006686631677018113 0.0008866874124157135 0.0007440327743919704 0.0009304131014551529 0.0005814299397160758 0.0010648434477783509 0.0009183489627890017 0.0004239725944496445 0.0005341670597258343 0.000576451191307805 0.0006589548224670541 0.0003622754702797734 0.0007495302760552053 0.0008448696097240493 0.0007138969914752706 0.0006575246169877966 0.0007249316169717899 0.0005741152648363746 0.0006147471826141572 0.0007997356796553269 0.0007778347652323488 0.0008690003186054852 0.0007256524288646954 0.0009299331492444872 0.0007743840354389615 0.0009591622728523907 0.0009020007349513178 0.000559755222833856 0.0006619681901540276 0.000713979237294059 0.0005889631583622089 0.000863440443912283 0.0006145512583291466 0.0007468192567333447 0.0006992921241140729 0.0007103558563154973 0.0008633419054996466 0.0005733737387722774 0.0007914126339008551 0.0012514110982711668 0.0008622021127955821 0.0005980703775501003 0.000700653564168626 0.0009120405539474175 0.000875585515525431 0.0007266650895836344 0.0004265783693812117 0.0006521518718345092 0.0005124619065816503 0.0004923006408059255 0.0007999620305938937 0.0012081612851983468 0.0008935328351092937 0.0009747528164537189 0.0007526206802701704 0.0009562998353617571 0.0009221615951393487 0.0004526283997919561 0.0007501979401291613 0.0006792407033835312 0.0009418241224837042 0.0009933871804938816 0.0008090888857165224 0.0010207535073878482 0.000824300854913575 0.0004411332775433643 0.0009822455247934403 0.0005584278250656128 0.0008877703972421927 0.0007580793962589777 0.0007663863102773332 0.0008605922280018232 0.0008086846120149574 0.000530847508782214 0.0005727563851087061 0.0008013865698785838 0.0011107323548744997 0.0010099690714047958 0.00037319999111541034 0.0008140689739195794 0.0005375612612210462 0.00063910747383142 0.0005425847990026908 0.0008037415767010002 0.0009097868293051404 0.0006095811690976755 0.0008416701707228973 0.0005423072476081243 0.0006486589625278647 0.0005367637947850263 0.0007693494308252405 0.000711008758454373 0.0008921888683283542 0.0008969566774610786 0.000842119786840999 0.0007265316634713728 0.0009227744525842186 0.0010881828110205858 0.000769784759877319 0.0002852821218126892 0.00078600213965086 0.0010140796668548107 0.0006790073530653253 0.0008440295525002012 0.0010101242557135272 0.0010180177710397583 0.0008462467667346788 0.0012228989677190464 0.0007445113149683374 0.0005706095400447219 0.0010449249119368167 0.0009395015242278339 0.0006968910296485923 0.0007501283795220349 0.000715685305438086 0.00048027337416580015 0.0010704746686966546 0.0008188810546293447 0.0009314103657909904 0.0005720666361682608 0.0012387022323280977 0.0007503426653680849 0.000601405282514845 0.0006481905274730637 0.0005601701838525855 0.0009236596566139973 0.0009677158401210994 0.0005632497639895169 0.0007675964782709339 0.0007563850652900144 0.0007182119902737943 0.0004906045529927696 0.0009007167560036245 0.000510807650533841 0.0007430984749102268 0.0007165927858411207 0.0005430495355291725 0.0007928403533148245 0.000876228226677745 0.0011251550047914488 0.0007529985067706059 0.0008333912348460475 0.000400081733537378 0.0009072571985814809 0.0005241527459227279 0.0010254036212703876 0.0007134183946210163 0.0009456546923780793 0.0006388634133473063 0.0009655762101426236 0.0006483664726507628 0.0006965500023781428 0.0006376498163030177 0.0003968958336100884 0.0004439596257893074 0.001130271687360053 0.000731480515879121 0.0005537891201286045 0.0008802977512820636 0.0009153645368225062 0.0005705148052624951 0.0007219917166105136 0.0004702245397953825 0.0007875775442662136 0.0010030209383180364 0.0007317042652216768 0.0012226228604856567 0.0014028119865632988 0.0005776767988588316 0.0009484531736954914 0.0009494748579465421 0.0007427817773937607 0.0007808385679751186 0.0011736248374371225 0.0011019851590723247 0.0006842860707850102 0.0006734618869398631 0.0007494740493314883 0.0009918981406768924 0.0009600657183434738 0.0004846155959183507 0.000841114666643091 0.0007772963410989715 0.0005115938318186999 0.0007122948496523184 0.0012270643951943446 0.0009600382451763617 0.0005977865737263712 0.0010619091723500583 0.0011519071770915248 0.0005393873336186615 0.0009928481976629834 0.0009084426302312609 0.0009933356693733499 0.0011135369000948644 0.0008355638213707572 0.0009594533651078643 0.00036590315768847995 0.0008008540464168165 0.0007920229835437993 0.0009819292408506208 0.0006139326998714905 0.0009092167669549826 0.0009835473860453111 0.0003476301786949354 0.0006498930670309982 0.0008240009448767369 0.001263893894153865 0.001214130826401816 0.000668180172453217 0.0010539626322570315 0.0005631421322522217 0.0007381333784743991 0.0013186753827719368 0.001192240939472783 0.0009910717530359802 0.0007157048270570837 0.0010651465270070418 0.0012565237924333024 0.000563033935165114 0.0005277377029486118 0.0007589859529664756 0.0004109897417342138 0.0006119105501833137 0.0009465129944708208 0.0001993255884156562 0.0008213984184820397 0.0008562907355875043 0.0010898114992350246 0.0005712057723414628 0.0008103874270986649 0.0010981089108472403 0.001172242375814217 0.0006561275173663624 0.0009301670280869443 0.0005544976110261636 0.0009525322948247709 0.0006271825626415179 0.001125280900550546 0.0010093400073160233 0.0004893138851278724 0.0007102925069228844 0.0004796042507685992 0.0008320952766252863 0.0010268093580907487 0.0009174270220115308 0.0009298890379354706 0.0007664565439431096 0.00096542694894379 0.0005316454657471359 0.001362406051977638 0.00126029833439878 0.0015002729509467304 0.0011691531469095273 0.0008467625790500536 0.0008035687520204203 0.0009614578466938769 0.0008010521678074861 0.00037759130230045174 0.0006589673155935706 0.0005303753656813506 0.0010126210280955714 0.0006258020382088416 0.0009121267248172789 0.0012313691157549722 0.001049065630478657 0.0011048100935120862 0.0006227969652011532 0.0007965724264743089 0.001387224270608414 0.0009522428644574411 0.0010089755272122036 0.0009822089101359638 0.0007677170225958986 0.0006316490723250939 0.0009377560502012278 0.001060987234789023 0.0007861907282201283 0.0012709343870376227 0.0010250970204928515 0.0010837771081950056 0.0009908547264889213 0.0010502152733814748 0.0005120218122460347 0.0007165366252357839 0.0012037113405740831 0.0006707983109259369 0.001389885479633844 0.0005303380245454641 0.0013554719630867475 0.000804813587291104 0.0005007846117488728 0.0008680012852792285 0.0008039899127962578 0.0005295077751178488 0.0010650687700154119 0.0007551182578845476 0.0007263976670925004 0.001212962372405825 0.00104476983342287 0.0008537036247692432 0.0014445821073785932 0.0012449688888018058 0.0015208393742885764 0.0007046003973507587 0.0013934568629435386 0.000914859236698767 0.0007052111127436618 0.0009159172738197191 0.0008778581715316999 0.0010087097539912607 0.0008271830385666752 0.0009360392861293037 0.0008113447613887953 0.00047815824762114945 0.0011067457725130881 0.0008807406021714571 0.0010666916953821813 0.0009577045844013372 0.0006305692589931498 0.0005800668701273395 0.0002048618975592093 0.0006069979497977569 0.000531196898201318 0.0008557851943482072 0.0009750142819443672 0.0009724848942666668 0.0012779415772484239 0.0008074434576826656 0.0008418842441015366 0.0010521237578863631 0.000778198047897382 0.00090376221369533 0.00043035694323763943 0.0008742855799754223 0.001293281901675596 0.0007827360789566337 0.0009870681543964024 0.001004847452866001 0.0012184345961668555 0.0007936755337952622 0.0010459014382046903 0.0009546634995085316 0.001257624167365295 0.0006774271075431505 0.0013639558210267054 0.001100473564927773 0.0012441102707288038 0.0014373857870888854 0.0009150286223557653 0.001209298528005329 0.0007652899916084731 0.0006996104804969957 0.0011260722891758136 0.0011549935018552535 0.0008307287635270463 0.0015058746045194355 0.0010516149892078987 0.0012029447762088293 0.0009149306184527473 0.0009740695125500079 0.0010794086464580963 0.0011349346613733482 0.0008975004855891622 0.001304870649803291 0.001215273303293898 0.0010795893817305833 0.0015884936773312161 0.0010729659479968908 0.0008753081888062908 0.0010974408944288906 0.0009228422478649721 0.0009758794772812533 0.00085299246003311 0.0008867787868433317 0.00124727278366698 0.0012353667203989379 0.0012427596285666108 0.0009222149551261983 0.0011844073632694104 0.0009044989823418179 0.001299040704567225 0.0013880283383311122 0.0010371915040593496 0.0010732780727615372 0.0009135192289410564 0.0012440904907508677 0.0009786975952165416 0.0005696430386582136 0.0011109918483655822 0.0012981570873818445 0.0012858002985194441 0.0011333129761868558 0.0009878432188965528 0.0009053147596283131 0.0009747363835909339 0.0007355339906187744 0.0010330339574952474 0.0009102039828842749 0.001056966511953838 0.0006762026603291838 0.001199470853799652 0.0012545676792113203 0.0007826816289715383 0.0010494180006627143 0.0008986454825122008 0.0008900709684340947 0.0006860818154401112 0.0009857076361018831 0.0003457653958055086 0.0005140022302885193 0.001423235888113857 0.0017553574125951088 0.001197126284837738 0.0007414652441424827 0.0008362348738906361 0.0008132245591619835 0.0011378570794584276 0.0015874003027109434 0.0009255086666005051 0.0009427273245087456 0.0010762379737519164 0.00098788523595807 0.001571019431385693 0.0002909997699635088 0.0010184338942693999 0.0014719939019106052 0.0012457295331779418 0.0011220279251867103 0.001320708704275924 0.0012399075686666584 0.001159364024075537 0.001244669399989565 0.0012067782961340619 0.0013108062922103081 0.0009618976139673397 0.0008071311636264934 0.0012848658844038863 0.0009171019086273589 0.0007996176051974812 0.0008036062149084962 0.0009072798476765115 0.000793089012937557 0.0009600554648462686 0.000992645257032026 0.0009686687940966474 0.0012243837521141365 0.001125806252093119 0.0007654719821346565 0.0013642862324606225 0.0011670301374839115 0.001604578434894504 0.0008374568788123102 0.0014986235006204862 0.0015701356411262878 0.0006657434022405598 0.0013845353661062413 0.001219384596471336 0.0008737768939108806 0.0010494510684420574 0.0009222086839748313 0.0012732347456471667 0.0011858684105957279 0.0019179000784992626 0.0013681221021490028 0.0013281836906744392 0.0012187595843030589 0.0013111683867050915 0.0011719458203592623 0.0013572137824939884 0.0010337098311431982 0.001638871465698339 0.0015604667950890121 0.001323508987236831 0.0020464741506832484 0.0006944878825225153 0.0011046410928042814 0.0014414804611452834 0.0018725218466401593 0.0002404324247984538 0.0010138722934900173 0.0013926979063741147 0.002070058176189564 0.0013019284617489528 0.0013038680434372446 0.0005397204832431734 0.0011923521522380076 0.0008886501333491859 0.0015010097035359769 0.0011247537153967642 0.0007845845804796413 0.0006219419716377376 0.0009462713723758497 0.001649494886433042 0.0014082798737966899 0.001072304075655831 0.0007545879915296843 0.0013142903219559607 0.0012673741886097404 0.0007686825089079977 0.0006515034405852395 0.0004003290511664357 0.0014643531373883926 0.0014171798819934101 0.0016449012501703376 0.002028157630601896 0.0006128944335396143 0.0016631742826592123 0.000723549828572489 0.0013736669987269787 0.0013823399008336121 0.0015810376356261368 0.0011949894572673926 0.001114578942759561 0.0018730136673697695 0.001196997041645648 0.0011722255970589652 0.0008370746042579171 0.0013974757415557363 0.0012688066121312469 0.0010424252641943875 0.001264977755400999 0.0010700943734532474 0.0017819146559548851 0.0005098494196810078 0.0018873505208473866 0.00105391094104933 0.0012466699162386396 0.0004211146137099592 0.001413056211171595 0.001274979235601838 0.0006545247733292137 0.001554598304774834 0.0011463541680346255 0.0014534359957203103 0.0013726032339994264 0.0011308452038855611 0.0013526290665061553 0.0007292296475314194 0.001469852110624965 0.0012256122574814128 0.0004780914210506476 0.0018306464300324543 0.0018831192531126237 0.0010960935296654283 0.0015125460384125887 0.000908354783661358 0.0011002741525626839 0.0018637255066985203 0.0013853153136580672 0.0015969960353949771 0.0009589572055989069 0.0008768182801056807 0.0007037782765468832 0.001902492166644584 0.0020202920907032972 0.0016411461982764198 0.0007455373517780349 0.0013984409733384937 0.0005833112587010457 0.0013941249451607156 0.0016020617420586616 0.0015153846262352937 0.002375857809950477 0.0005340868158132004 0.0008373689872912367 0.001308614247178495 0.0016996779250921489 0.0014141078045271478 0.0015680206621989548 0.0002940026955455891 0.0017030333611348387 0.001195380218694524 0.001806235301558795 0.0010875513922395253 0.0010830733497866878 0.000822317038180907 0.000567722870710013 0.000583568662936589 0.001134118688231472 0.0010025636436904871 0.0005573334444183738 0.0019287841154301936 0.0007634713852630136 0.0012448222272147791 0.0015882791656856592 0.0016850549761983043 0.0008877585912039505 0.00104969676415809 0.0014213751108184158 0.0015169425682421463 0.0004905417410219729 0.0024447412335600665 0.0020835912947756554 0.0018555286072899496 0.0017174195510289902 0.0013937253225056964 0.001467637469255164 0.002532695504216574 0.0015400182099285682 0.0013298598275832457 0.0009850053591270987 0.001571467265404312 0.0013749691850085618 0.002009538941291626 0.0020580068757073606 0.0015042087068884266 0.0024265628730326897 0.0011724249798647946 0.0012647737606120157 0.0014387314832090801 0.0019044943735031447 0.0014317002205580668 0.001062507055779056 0.0013849884348921858 0.0011984775734875351 0.0010121218745125307 0.0014409430939625546 0.0012407462596961648 0.0003437158726665955 0.0016447246383843974 0.0011422292134610546 0.000563097823904911 0.0015765128968950914 0.001505823615162113 0.0017650607218414195 0.0010931119982941712 0.0015125881789526316 0.001361209028585102 0.0006658072320213478 0.00136505909113486 0.001795809851104738 0.0012095923801153348 0.0009776784083181758 0.001627853713850087 0.003023318742709796 0.0016614407782219395 0.0018098704690599993 5.81011264298683e-7 0.0016751546512679446 0.0010344924476244288 0.0008936426090566522 0.0009398686913127734 0.00047546344948500084 0.00084704209531371 0.0005997781107622372 0.0009820247785840939 0.0016008420932675368 0.001361524326786464 0.0011681406116652465 0.0007100794777450526 0.001622593049100077 0.0019312043562599314 0.001955834940734043 0.001300186661130563 0.0008473059639885839 0.0008468296030323799 0.001797805964100868 0.0010032311409894144 0.0008254800640423295 0.0018715669514508166 0.0014605540571477505 0.0018592754796626031 0.0020846651286845486 0.0009005262697593812 0.0009571855578512618 0.0007755804271232539 0.002529844628074969 0.0013351552794298276 0.00129525142595085 0.0022310082213243803 0.0006986957744983211 0.002103264606915408 0.0011158356780163537 0.0011111673909054121 0.0029762941670259916 0.0015918008277034997 0.0014271555841840762 0.0012700077047275167 0.0020324459041304106 0.001442032023090879 0.0020929878441526186 0.002340007075902152 0.0012774323788884406 0.0015995389199063644 0.0021912024186273352 0.0016967336259560508 0.001153798746508344 0.0008731025062233751 0.0013082968275565116 0.001690519897314452 0.0012804431431907733 0.0020546201946592267 0.0013561974403580727 0.001266082254498757 0.001892325369974752 0.0007921558062621175 0.0017086246313910208 6.949962975098176e-6 0.0009307040010744052 0.0005748508210090921 0.0015303236497021776 0.0017467876141135695 0.001302979438345667 0.0018759164807104684 0.00029491744444495616 0.0015776081131344969 0.0025614829713955503 0.0008605819278327193 0.0012447307949637822 0.00043463089799912214 0.0016578433246198525 0.000815010473203796 0.0004851853614444267 0.0019280940726462315 0.001617598884767852 0.0019658389117368016 0.00199361309800802 0.0018354567334096302 0.00254454699600168 0.002217324416727356 0.00020554106276034323 0.0028145695570283478 0.002013541408952003 0.001427609469811477 0.001326367675877524 0.001859069809545089 0.001927764537984837 0.0008969343729452774 0.002078938862771566 0.0021103409071436545 0.0006483807209883566 0.0015428676568223507 0.001257208211624372 0.0008834221452461365 0.0015244953917749255 0.0028480773692240026 0.0018884456043282579 0.0025703151678374485 0.0009733015287772254 0.0012406806699404723 0.000825756285923428 0.001661907000244604 0.0013403525174255958 0.0018343613983112187 0.0014820134576503778 0.002440746528070622 0.0014174054859715324 0.0018759569749941705 0.0016341317196305928 0.001541797791549588 0.000992750475183311 0.0016770105069908708 0.002235592362869389 0.0015017703376287138 0.0017447638527936112 0.0012431075209464906 0.0003018377398732817 0.0015932204974133267 0.001230847072724235 0.0014563964500322218 0.0016790782662605439 0.00026283670948781037 0.0005712391136852477 0.0028085016499335125 0.0018019701057805566 0.0003064629036626991 0.0014811442176186575 0.0018039038548974629 0.00028317267206120215 0.00024862450480226295 0.0018686430495926452 0.0017277721090188012 0.0024070333194674606 0.0001558851165436762 0.0010741548411589336 0.0004448681469482655 0.00019681498154585912 0.001446134649364775 0.0001782602423671078 0.001572887742816197 0.0009669269619178688 0.0025982218580254167 0.00015167827544595842 0.0013517075511813733 0.00205691555242792 0.0006073052864186683 0.0020412513788273775 0.003393092480228378 0.0018897397822988816 0.001149990511353958 0.0010821906311782121 0.002851342859243226 0.0014734653533826877 0.0016072821764510686 0.0019847898616487747 0.0019621598795614608 0.0014846721652844804 0.0007214393476589174 0.0008889890825044406 0.0023808823038167274 0.0011340363384867312 0.0014418176734341326 0.0014944995775858685 0.001990670436878294 0.002006162646462098 2.069100195298758e-8 0.0009544520116727861 0.0017156444671249482 0.0005094174546272584 0.0010241570292064117 0.0010685199587167325 0.0004952150553333657 0.0004213770763419892 0.002216648793494301 0.0026943170022276945 0.001834457520298822 0.0019885956520496236 0.0020503542686098673 0.0006304769498759658 0.0014401053336811508 6.302480035028645e-5 0.001782867032118198 0.0012045258835450886 0.0004823897040521397 0.0005625297908514997 0.001440197815383483 0.0013486029633553785 1.9390007323059745e-7 0.0005823586970054247 0.0024205585903942714 0.0011474378590624731 3.8045824671111825e-7 7.693052885519039e-6 0.0004444258117343846 3.781876683450104e-8 0.0005520312008172473 0.0015434974485103474 0.002117148334089267 0.0001070764197520101 0.0018981206819769396 0.0017519276443864714 0.0014854224702340135 0.000221177581938812 7.633865306674882e-8 1.0009620529554144e-8 0.0018401050947693945 0.0017163227800480927 0.000931208569586141 0.0015806656968959905 0.003321682773356534 0.0016368228694436297 0.0009913897099568239 1.473166501306075e-8 0.0014498251618949955 1.3948583551688246e-8 0.0009316047544549441 5.937529256299154e-9 0.00193065769549726 0.0005305235461135298 0.0006493219161140218 2.8573732186876556e-6 0.0014537525382374566 0.00015266633814638752 0.0002541750223931143 0.0009667350373490413 0.0015993939952722888 2.8402054409721615e-5 9.443498416971869e-5 0.0008573864516430176 0.0007455686150873769 7.320381847940819e-5 0.0007127251076300434 1.944331045862745e-5 0.0012674457981787619 0.0019188022246958497 0.0001402654102448549 9.8748760962498e-9 0.002054071260533966 0.00032206338860479985 5.2255491489495424e-5 0.00028572546709341377 5.8588948699880206e-9 2.930928263810757e-7 0.0008615162795497163 1.6969783960814416e-8 4.677856600305364e-6 6.128424942519684e-6 5.147568343143185e-7 1.5363778323122724e-8 1.719564046229023e-8 4.2253200728789876e-7 0.0030336343505796854 2.6013959898789606e-8 7.408058897525929e-7 2.5964703214561624e-8 1.4781902086346327e-7 0.0016789457944545157 4.0792785976707164e-9 1.184126431594396e-8 0.0014212035553242807 7.918256581302968e-9 1.376527069421637e-8 1.2551192458839895e-6 6.625738746305198e-8 1.1051207905687645e-8 1.0112057334760872e-8 8.763479755492427e-9 3.170223736631503e-8 7.754808371656717e-8 1.0753547828904632e-7 0.0001441470990366897 4.667039213137739e-9 8.086761919908992e-9 3.1025670985930674e-9 2.0358879212685844e-9 2.4875895111223026e-8 7.94646708984332e-9 4.802628614294363e-9 6.479091082103819e-9 3.186251897212768e-8 1.3168881627474778e-8 4.767294979004821e-9 1.314198741983399e-8 1.47370549584402e-8 5.817726412970424e-9 9.867884881361152e-7 3.2943264682696006e-8 5.410852189184902e-9 1.352715654281171e-8 3.635064422711831e-9 3.026385420868993e-9 5.699668300672657e-9 2.567713288161805e-8 3.946371264193405e-9 3.6927865416000654e-9 2.838089517254119e-9 3.962423881746877e-9]
user_initial_guess = user_initial_guess'

max_stars_repo_name: rohitkannan/SA-for-CCP

max_issues_repo_name: rohitkannan/SA-for-CCP

max_forks_repo_name: rohitkannan/SA-for-CCP


text:
#=

Author: Shunsuke Hori

=#

"""
This holds the results for Harrison Kreps.  In particular, it
accepts two matrices Qa and Qb and compares the single belief,
optimistic belief, and pessimistic belief prices
"""
struct PriceHolder{TF<:AbstractFloat}
    qa::Matrix{TF}
    qb::Matrix{TF}
    qpess::Matrix{TF}
    qopt::Matrix{TF}
    dividend_payoff::Vector{TF}
    qaprice::Vector{TF}
    qbprice::Vector{TF}
    qpessprice::Vector{TF}
    qoptprice::Vector{TF}
    optimisticprice::Vector{TF}
    pessimisticprice::Vector{TF}
    phat_a::Vector{TF}
    phat_b::Vector{TF}
end

function PriceHolder{TF<:AbstractFloat}(qa::Matrix,
                                        qb::Matrix,
                                        dividend_payoff::Vector;
                                        beta::TF=.75,
                                        max_iters::Integer=10000,
                                        tolerance::TF=1e-16)

    # Create the Pessimistic and Optimistic Beliefs
    qpess = Array{TF}(2, 2)
    qpess[1, :] = ifelse(qa[1, 2] < qb[1, 2], qa[1, :], qb[1, :])
    qpess[2, :] = ifelse(qa[2, 2] < qb[2, 2], qa[2, :], qb[2, :])
    qopt = Array{TF}(2, 2)
    qopt[1, :] = ifelse(qa[1, 2] > qb[1, 2], qa[1, :], qb[1, :])
    qopt[2, :] = ifelse(qa[2, 2] > qb[2, 2], qa[2, :], qb[2, :])

    # Price everything
    p_singlebelief, p_optimistic, phat_a, phat_b, p_pessimistic=
        create_prices(qa, qb, qpess, qopt, dividend_payoff,
                                    beta,max_iters,tolerance)

    qaprice = p_singlebelief[1]
    qbprice = p_singlebelief[2]
    qpessprice = p_singlebelief[3]
    qoptprice = p_singlebelief[4]

    return PriceHolder(qa,
                        qb,
                        qpess,
                        qopt,
                        dividend_payoff,
                        qaprice,
                        qbprice,
                        qpessprice,
                        qoptprice,
                        p_optimistic,
                        p_pessimistic,
                        phat_a,
                        phat_b)
end

"""
Computes prices under all belief systems
"""
function create_prices(qa::Matrix, qb::Matrix, qpess::Matrix, qopt::Matrix,
                       dividend_payoff::Vector, bet::AbstractFloat,
                       max_iters::Integer, tolerance::AbstractFloat)
    transitionmatrix = [qa, qb, qpess, qopt]
    # Single Belief Prices
    p_singlebelief = [price_singlebeliefs(q, dividend_payoff, beta=bet)
                         for q in transitionmatrix]

    # Compute Optimistic and Pessimistic beliefs
    p_optimistic, phat_a, phat_b =
        price_optimisticbeliefs([qa, qb], dividend_payoff,
                    beta=bet, max_iter=max_iters, tol=tolerance)
    p_pessimistic =
        price_pessimisticbeliefs([qa, qb], dividend_payoff,
                    beta=bet, max_iter=max_iters, tol=tolerance)

    return p_singlebelief, p_optimistic, phat_a, phat_b, p_pessimistic
end

function print_prices(ph::PriceHolder)
    qaprice, qbprice, qpessprice, qoptprice =
        ph.qaprice, ph.qbprice, ph.qpessprice, ph.qoptprice
    optimisticprice, pessimisticprice =
        ph.optimisticprice, ph.pessimisticprice
    phata, phatb = ph.phat_a, ph.phat_b
    println("The Single Belief Price Vectors are:")
    println(" P(Qa) = $(qaprice)\n P(Qb) = $(qbprice)\n P(Qopt) = $(qoptprice)\n P(Qpess) = $(qpessprice)\n")
    println("The Optimistic Belief Price Vector is:")
    println(" P(Optimistic) = $(optimisticprice)\n Phat(a) = $(phata)\n Phat(b) = $(phatb)\n")
    println("The Pessimistic Belief Price Vector is:")
    println(" P(Pessimistic) = $(pessimisticprice)")
end

ph=PriceHolder(qa, qb, [0.0, 1.0], beta=0.75)

print_prices(ph)


text:
module Styles

using LaTeXStrings

export Quiver

Quiver = L"""
% contents of quiver.sty
% `tikz-cd` is necessary to draw commutative diagrams.
\RequirePackage{tikz-cd}
% `amssymb` is necessary for `\lrcorner` and `\ulcorner`.
\RequirePackage{amssymb}
% `calc` is necessary to draw curved arrows.
\usetikzlibrary{calc}
% `pathmorphing` is necessary to draw squiggly arrows.
\usetikzlibrary{decorations.pathmorphing}

% A TikZ style for curved arrows of a fixed height, due to AndréC.
\tikzset{curve/.style={settings={#1},to path={(\tikztostart)
    .. controls ($(\tikztostart)!\pv{pos}!(\tikztotarget)!\pv{height}!270:(\tikztotarget)$)
    and ($(\tikztostart)!1-\pv{pos}!(\tikztotarget)!\pv{height}!270:(\tikztotarget)$)
    .. (\tikztotarget)\tikztonodes}},
    settings/.code={\tikzset{quiver/.cd,#1}
        \def\pv##1{\pgfkeysvalueof{/tikz/quiver/##1}}},
    quiver/.cd,pos/.initial=0.35,height/.initial=0}

% TikZ arrowhead/tail styles.
\tikzset{tail reversed/.code={\pgfsetarrowsstart{tikzcd to}}}
\tikzset{2tail/.code={\pgfsetarrowsstart{Implies[reversed]}}}
\tikzset{2tail reversed/.code={\pgfsetarrowsstart{Implies}}}
% TikZ arrow styles.
\tikzset{no body/.style={/tikz/dash pattern=on 0 off 1mm}}
"""

end


text:
module Day8

using ..Utils
using BenchmarkTools

function seven_permutation(n::Int)
    result = zeros(Int, 7)
    digits = Array{Int}(1:7)
    m = n
    for i in 7:-1:1
        k = digits[m % i + 1]
        result[i] = k
        m = m ÷ i
        filter!(x -> x!=k, digits)
    end
    result
end

function count_unique_digits(input)
    lines = filter(!isempty, split(input, "\n"))
    uniques = 0
    for line in lines
        outputs = split(line, " | ")[2] |> split
        for output in outputs
            if length(output) ∈ [2, 3, 4, 7]
                uniques += 1
            end
        end
    end
    uniques
end

function decode(input)
    for line in lines
        decodeline(input)
    end
end

initial_possibilities() = begin
    p = Dict()
    for i in 1:7
        push!(p, i=>["a", "b", "c", "d", "e", "f", "g"])
    end
    p
end

toints(symbol) = [findfirst(ch, "abcdefg") for ch in symbol]
fromints(ints) = "abcdefg"[ints]

Base.:-(s1::Union{AbstractString, Vector{Char}},
        s2::Union{AbstractString, Vector{Char}}) = setdiff(s1, s2)

function decodeline(line)
    code = split(line, " | ")[1] |> split
    code = sort(code, by=length)
    sols = Dict()

    all = "abcdefg"
    # [1 2 3 4 5 6 7 8 9 10]
    # [1 7 4 2 3 5 6 9 0 8]
    # [0 1 2 3 4 5 6 7 8 9]
    # The top row is included in "7" but not "1"
    sols['a'] = (code[2] - code[1]) |> only
    # Bars not contained in 6, 9, or 0.
    # Should be c, d, e.
    complement_690 = all - (code[7] ∩ code[8] ∩ code[9])
    sols['c'] = (code[1] ∩ complement_690) |> only
    sols['f'] = code[1] - [sols['c']] |> only
    sols['d'] = complement_690 ∩ (code[3] - code[1]) |> only
    sols['e'] = (complement_690 - [sols['c'], sols['d']]) |> only
    # Bar b is contained in 4 and in the complement of (2, 3, 5),
    sols['b'] = code[3] - [sols['c'], sols['d'], sols['f']] |> only
    sols['g'] = all - [sols[ch] for ch in "abcdef"] |> only

    coding = Dict()

    for (from, to) in sols
        push!(coding, to => from)
    end
    coding
end

function decode_digit(time::AbstractString, coding::Dict)
    bars = [coding[ch] for ch in time]
    if length(bars) == 2
        return 1
    elseif length(bars) == 3
        return 7
    elseif length(bars) == 4
        return 4
    elseif length(bars) == 7
        return 8
    elseif length(bars) == 5
        if isempty("acdeg" - bars)
            return 2
        elseif isempty("abdfg" - bars)
            return 5
        elseif isempty("acdfg" - bars)
            return 3
        end
    elseif length(bars) == 6
        if isempty("abdefg" - bars)
            return 6
        elseif isempty("abcdfg" - bars)
            return 9
        elseif isempty("abcefg" - bars)
            return 0
        end
    else
        return 8
    end
end

function decode_time(time::AbstractString, coding::Dict)
    digits = split(time)
    time = 0
    for digit in digits
        d = decode_digit(digit, coding)
        time *= 10
        time += d
    end
    time
end

function add_up_times(input::String)
    sum = 0
    for line in filter(!isempty, split(input, "\n"))
        coding = decodeline(line)
        time = split(line, " | ")[2]
        sum += decode_time(time, coding)
    end
    sum
end

test = """
be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe
edbfga begcd cbg gc gcadebf fbgde acbgfd abcde gfcbed gfec | fcgedb cgb dgebacf gc
fgaebd cg bdaec gdafb agbcfd gdcbef bgcad gfac gcb cdgabef | cg cg fdcagb cbg
fbegcd cbd adcefb dageb afcb bc aefdc ecdab fgdeca fcdbega | efabcd cedba gadfec cb
aecbfdg fbg gf bafeg dbefa fcge gcbea fcaegb dgceab fcbdga | gecf egdcabf bgf bfgea
fgeab ca afcebg bdacfeg cfaedg gcfdb baec bfadeg bafgc acf | gebdcfa ecba ca fadegcb
dbcfg fgd bdegcaf fgec aegbdf ecdfab fbedc dacgb gdcebf gf | cefg dcbef fcge gbcadfe
bdfegc cbegaf gecbf dfcage bdacg ed bedf ced adcbefg gebcd | ed bcgafe cdgba cbgef
egadfb cdbfeg cegd fecab cgb gbdefca cg fgcdab egfdb bfceg | gbdfcae bgc cg cgb
gcafb gcf dcaebfg ecagb gf abcdeg gaef cafbge fdbac fegbdc | fgae cfgab fg bagce
"""

function run()
    @assert count_unique_digits(test) == 26

    input = read("resources/day8_input.txt", String)
    count_unique_digits(input) |> display

    @assert add_up_times(test) == 61229
    add_up_times(input) |> display

    @btime add_up_times($input)
end

end


text:
using JuliaDB
using Base.Test

@testset "map & reduce" begin
    t = NDSparse(Columns([1,1,2,2], [1,2,1,2]), [1,2,3,4])
    d = distribute(t, 2)
    @test collect(map(-, d)) == map(-, t)
    @test reduce(+, d) == 10
end

@testset "getindex" begin
    t = NDSparse(Columns(x=[1,1,1,2,2], y=[1,2,3,1,2]), [1,2,3,4,5])
    for n=1:5
        d = distribute(t, n)

        @test d[1,1] == t[1,1]
        @test d[1,3] == t[1,3]
        @test d[2,2] == t[2,2]

        @test collect(d[1:1, 1:1]) == t[1:1, 1:1]
        @test collect(d[1:2, 2:3]) == t[1:2, 2:3]
        @test collect(d[:, 3]) == t[:, 3]
    end
end

@testset "select" begin

    t = NDSparse(Columns(a=[1,1,1,2,2], b=[1,2,3,1,2]), [1,2,3,4,5])
    for i=[1, 3, 5]
        d = distribute(t, i)

        res = filter((1=>x->true, 2=>x->x%2 == 0), t)
        @test collect(filter((1=>x->true, 2=>x->x%2 == 0), d)) == res
        @test collect(filter((:a=>x->true, :b => x->x%2 == 0), d)) == res
    end
end

function Base.isapprox(x::NDSparse, y::NDSparse)
    flush!(x); flush!(y)
    all(map(isapprox, x.data.columns, y.data.columns))
end

@testset "convertdim" begin

    t = NDSparse(Columns(a=[1,1,1,2,2], b=[1,2,3,1,2]),
                     Columns(c=[1,2,3,4,5], d=[5,4,3,2,1]))

    _plus(x,y) = map(+,x, y)

    for i=[2, 3, 5]
        d = distribute(t, i)
        @test collect(convertdim(d, 2, x->x>=2)) == convertdim(t, 2, x->x>=2)
        @test collect(convertdim(d, 2, x->x>=2, agg=_plus)) == convertdim(t, 2, x->x>=2, agg=_plus)
        @test collect(convertdim(d, 2, x->x>=2, vecagg=length)) ==
                convertdim(t, 2, x->x>=2, vecagg=length)
    end
end

@testset "reducedim" begin
    t1 = NDSparse(Columns([1,1,2,2], [1,2,1,2]), [1,2,3,4])
    rd1 = reducedim(+, t1, 1)
    rd2 = reducedim(+, t1, 2)
    rdv1 = reducedim_vec(length, t1, 1)
    rdv2 = reducedim_vec(length, t1, 2)

    for n=1:5
        d1 = distribute(t1, n, allowoverlap=true)
        @test collect(reducedim(+, d1, 1)) == rd1
        @test collect(reducedim(+, d1, 2)) == rd2

        @test collect(reducedim_vec(length, d1, 1)) == rdv1
        @test collect(reducedim_vec(length, d1, 2)) == rdv2
    end
end

@testset "select" begin
    t1 = NDSparse(Columns([1,2,3,4], [2,1,1,2]), [1,2,3,4])
    d1 = distribute(t1, 2)
    @test collect(selectkeys(d1, 2, agg=+)) == selectkeys(t1, 2, agg=+)
end

@testset "permutedims" begin
    t = NDSparse(Columns([1,1,2,2], ["a","b","a","b"]), [1,2,3,4])
    for n=1:5
        d = distribute(t, n)
        @test collect(permutedims(d, [2,1])) == permutedims(t, [2,1])
    end
end

@testset "mapslices" begin
    t = NDSparse(Columns(x=[1,1,2,2], y=[1,2,3,4]), [1,2,3,4])

    for (dist,) in zip(Any[1, 2, [1,3], [3,1], [1,2,1]])
        d = distribute(t, dist)
        res = mapslices(collect, d, :y)
        @test collect(res) == mapslices(collect, t, 2)
        f = x->IndexedTables.NDSparse(IndexedTables.Columns(z=[1,2]), [3,4])
        res2 = mapslices(f, d, 2)
        @test collect(res2) == mapslices(f, t, 2)
    end
    t = ndsparse([1,2,3],[4,5,6], chunks=2)
    @test mapslices(t, ()) do x
        IndexedTables.ndsparse([1,2], first.([x,x]))
    end == ndsparse(([1,1,2,2,3,3],[1,2,1,2,1,2],), [4,4,5,5,6,6])
end

@testset "flatten" begin
    x = table([1,2], [[3,4], [5,6]], names=[:x, :y], chunks=2)
    @test flatten(x, 2) == table([1,1,2,2], [3,4,5,6], names=[:x,:y])

    x = table([1,2], [table([3,4],[5,6], names=[:a,:b]), table([7,8], [9,10], names=[:a,:b])], names=[:x, :y], chunks=2)
    @test flatten(x, :y) == table([1,1,2,2], [3,4,7,8], [5,6,9,10], names=[:x,:a, :b])

    t = table([1,1,2,2], [3,4,5,6], names=[:x,:y], chunks=2)
    @test groupby((:normy => x->Iterators.repeated(mean(x), length(x)),),
                  t, :x, select=:y, flatten=true) == table([1,1,2,2], [3.5,3.5,5.5,5.5], names=[:x, :normy])
end


text:
using KMarkovGenSeq, FASTX

function ground_truth_classification()
    descriptions_dict = Dict{String, Int}()
    for (idx, dbseq) in readdir("data/genomes") |> enumerate
        db_seq_path = joinpath("data/genomes", dbseq)
        reader = open(FASTA.Reader, db_seq_path) #read one db seq
        record = FASTA.Record()
        read!(reader, record)
        descriptions_dict[description(record)] = idx
        close(reader)
    end

    gt_cls = Int[]
    for line in eachline("data/seq_id.map")
        push!(gt_cls, descriptions_dict[split(line, '\t')[end]])
    end
    gt_cls
end

function main()
    gt_cls = ground_truth_classification()
    len = gt_cls |> length
    best_k, best_acc = 0, 0
    des = String[]
    for k in 3:9
        _, pred_cls, des = query_freq("data/test.fa", "data/genomes", k, nothing, false)
        acc = sum(gt_cls[i] == pred_cls[i] for i in 1:len)
        if acc > best_acc
            best_acc = acc
            best_k = k
        end
        @info "k = $k, accuracy = $(acc/len)"
    end
    println("The best k is $best_k with accuracy ", best_acc / len)

end

main()

"""
[ Info: k = 3, accuracy = 0.60725
[ Info: k = 4, accuracy = 0.63815
[ Info: k = 5, accuracy = 0.65865
[ Info: k = 6, accuracy = 0.68475
[ Info: k = 7, accuracy = 0.7535
[ Info: k = 8, accuracy = 0.8921
[ Info: k = 9, accuracy = 0.9837
The best k is 9 with accuracy 0.9837
"""


text:
using PSPlot
@static if VERSION < v"0.7.0-DEV.2005"
    using Base.Test
else
    using Test
end

# write your own tests here
using PyPlot
plot(1:10)
printfig("output.eps")
@test true
rm("output.eps")


text:
int main() {
  int x;
  for(int i : x) {
    int y = i;
  }
  return 0;
}

max_stars_repo_name: fredefox/javalette

max_issues_repo_name: fredefox/javalette

max_forks_repo_name: fredefox/javalette


text:
#### Taken from LineSearches.jl. See backtracking for information.

"""
Provide static initial step length.

Keyword `alpha` corresponds to static step length, default is 1.0.
If keyword `scaled = true`, then the initial step length
is scaled with the `l_2` norm of the step direction.
"""
struct InitialStatic{T,S}
    alpha::T
    # scaled::Bool = false # Scales step. alpha ← min(alpha,||s||_2) / ||s||_2
end
InitialStatic() = InitialStatic{Float64,false}(1.0)
InitialStatic(α::T) where {T} = InitialStatic{T,false}(α)
InitialStatic(α::T,::Val{S}) where {T,S} = InitialStatic{T,S}(α)

function (is::InitialStatic{T,true})(ls, state, phi_0, dphi_0, df) where T
    PT = promote_type(T, real(eltype(state.s)))
    state.alpha = convert(PT, min(is.alpha, ns)) / ns
end

function (is::InitialStatic{T,false})(ls, state, phi_0, dphi_0, df) where T
    PT = promote_type(T, real(eltype(state.s)))
    state.alpha = convert(PT, is.alpha)
end


text:
Pkg.add(["TimeSeries", "MarketData", "Plots", "Pipe"])
using Pipe: @pipe
using TimeSeries, MarketData, Plots
# include("src/Portfolio.jl")
using Portfolio

function strategy_tearsheet(weights::Weights, returns::Returns)
    strategy_returns = run_weights(returns, weights, 0.0)
    equity_curves = plot(TimeSeries.merge(equity_curve(returns), equity_curve(strategy_returns)))
    plot(
        equity_curves,
        plot(weights),
        size = (1200, 1200),
        layout = grid(2, 1, heights = [0.8, 0.2])
    )
end
yahoo(:TLT)

@time dell = DELL[:AdjClose] |> percentchange
@time aapl = AAPL[:AdjClose] |> percentchange

assets = merge(dell, aapl)

strategy_tearsheet(Portfolio.strategy_static_equal_weights(assets), assets)
strategy_tearsheet(Portfolio.strategy_static_equal_weights(assets) |> Portfolio.rebalance_once, assets)

run_weights(assets, Portfolio.strategy_static_equal_weights(assets) |> Portfolio.rebalance_once)

Portfolio.strategy_static_equal_weights(assets) |> Portfolio.rebalance_once


text:
function read_VolumeImage(fname::AbstractString)

    @info("Creating volume image from file $fname")

    if contains(fname, ".dat")
        x, y, z, s, t = read_dat(fname)
        method = "CLARA"
        header = Dict()
        units = "nAm/cm^3"
        x = x/1000
        y = y/1000
        z = z/1000
        t = t/1000
    else
        @warn("Unknown file type")
    end

    header["FileName"] = fname

    coord_system = "?"

    VolumeImage(s, units, collect(x) * u"m", collect(y) * u"m", collect(z) * u"m", collect(t) * u"s", method, header, coord_system)
end


text:
struct Delay
    T::Real #Time in [s]
    function Delay(T)
		T < 0 ? error("Delays must be positive.") : new(T)
    end
end
#Interactions with other objects are context aware object
#Sequence contatenation
+(s::Sequence, d::Delay) = s + Sequence([Grad(0.,d.T)])
+(d::Delay, s::Sequence) = Sequence([Grad(0.,d.T)]) + s
#aux
Base.show(io::IO,s::Delay) = begin
	print(io, "Delay($(s.T*1e3)ms)")
end


text:
module TestAqua

using Aqua
using Setfield
using Test
using Transducers

Aqua.test_all(
    Transducers;
    # https://github.com/JuliaCollections/DataStructures.jl/pull/511
    ambiguities = (; exclude = [Base.get, Setfield.set, Setfield.modify, map!]),
    unbound_args = false,  # TODO: make it work
)

@testset "Compare test/Project.toml and test/environments/main/Project.toml" begin
    @test Text(read(joinpath(@__DIR__, "Project.toml"), String)) ==
          Text(read(joinpath(@__DIR__, "environments", "main", "Project.toml"), String))
end

end  # module


text:
function get_perm(str::String)
    p = Array(Int, length(str))
    for (i,c) in enumerate(str)
        p[i] = char2ind(c)
    end
    p
end

const ENIGMA_ROTORS = [
    Rotor(get_perm("EKMFLGDQVZNTOWYHXUSPAIBRCJ"), Int[2]), #char2ind('Q')]), # I
    Rotor(get_perm("AJDKSIRUXBLHWTMCQGZNPYFVOE"), Int[5]), # char2ind('E')]), # II
    Rotor(get_perm("BDFHJLCPRTXVZNYEIWGAKMUSQO"), Int[char2ind('V')]), # III
    Rotor(get_perm("ESOVPZJAYQUIRHXLNFTGKDCMWB"), Int[char2ind('J')]), # IV
    Rotor(get_perm("VZBRGITYUPSDNHLXAWMJQOFECK"), Int[char2ind('Z')]), # V
    Rotor(get_perm("JPGVOUMFYQBENHZRDKASXLICTW"), Int[char2ind('Z'), char2ind('M')]), # VI
    Rotor(get_perm("NZJHGRCXMYSWBOUFAIVLPEKQDT"), Int[char2ind('Z'), char2ind('M')]), # VII
    Rotor(get_perm("FKQHTLXOCBJSPDZRAMEWNIUYGV"), Int[char2ind('Z'), char2ind('M')]), # VIII
]

const ENIGMA_REFLECTORS = [
    Reflector(get_perm("YRUHQSLDPXNGOKMIEBFZCWVJAT")), # b
    Reflector(get_perm("FVPJIAOYEDRZXWGCTKUQSBNMHL")), # c
    Reflector(get_perm("ENKQAUYWJICOPBLMDXZVFTHRGS")), # b - thin
    Reflector(get_perm("RDOBJNTKVEHMLFCWZAXGYIPSUQ")), # c - thin
]

function get_M3_enigma(
    ref::Char, # 'B' or 'C'
    wheels::Tuple{Int, Int, Int},
    rotor_pos::String, # the starting rotor positions, ex: "DVM"
    plugboard_str::String=""; # ex: "BI GP HK LD MO RT VS WZ XN YJ"
    emulate_double_stepping::Bool=true,
    )

    if ref == 'B'
        reflector = ENIGMA_REFLECTORS[1]
    elseif ref == 'C'
        reflector = ENIGMA_REFLECTORS[2]
    else
        error("unknown reflector $ref")
    end

    rotors = ENIGMA_ROTORS[[wheels[3], wheels[2], wheels[1]]]
    rotors[1].rotor_position = rotor_pos[3]-'A'
    rotors[2].rotor_position = rotor_pos[2]-'A'
    rotors[3].rotor_position = rotor_pos[1]-'A'

    plugboard = Plugboard(collect(1:26))
    plugboard_str = replace(plugboard_str, " ", "")
    i = 1
    while i < length(plugboard_str)
        a = char2ind(plugboard_str[i])
        b = char2ind(plugboard_str[i+1])
        plugboard.perm[a] = b
        plugboard.perm[b] = a
        i += 2
    end

    alphabet = collect('A':'Z')
    Enigma(plugboard, rotors, reflector, alphabet, emulate_double_stepping)
end

function encode!(enigma::Enigma, input::String)
    output = ""
    for c in input
        output = output * string(ind2char(encode!(enigma, char2ind(c))))
    end
    output
end

let
    enigma = get_M3_enigma('B', (1,2,3), "AAA")
    input =  "THEQ"*"UICK"*"BROW"*"NFOX"*"JUMP"*"EDOV"*"ERTH"*"ELAZ"*"YDOG"
    output = "OPCI"*"LLAZ"*"FXLQ"*"TDNL"*"GGLE"*"YOHH"*"CJGA"*"XWTW"*"AMBH"
    @assert encode!(enigma, input) == output

    enigma = get_M3_enigma('B', (1,2,3), "AAA")
    @assert encode!(enigma, output) == input

    enigma = get_M3_enigma('B', (1,2,3), "AAA")
    input2 = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
    output = "BDZGOWCXLTKSBTMCDLPBMUQOFXYHCXTGYJFLINHNXSHIUNTHEORXPQPKOVHCBUBTZSZSOOSTGOTFSODBBZZLXLCYZXIFGWFDZEEQIBMGFJBWZFCKPFMGBXQCIVIBBRNCOCJUVYDKMVJPFMDRMTGLWFOZLXGJEYYQPVPBWNCKVKLZTCBDLDCTSNRCOOVPTGBVBBISGJSOYHDENCTNUUKCUGHREVWBDJCTQXXOGLEBZMDBRZOSXDTZSZBGDCFPRBZYQGSNCCHGYEWOHVJBYZGKDGYNNEUJIWCTYCYTUUMBOYVUNNQUKKSOBSCORSUOSCNVROQLHEUDSUKYMIGIBSXPIHNTUVGGHIFQTGZXLGYQCNVNSRCLVPYOSVRBKCEXRNLGDYWEBFXIVKKTUGKPVMZOTUOGMHHZDREKJHLEFKKPOXLWBWVBYUKDTQUHDQTREVRQJMQWNDOVWLJHCCXCFXRPPXMSJEZCJUFTBRZZMCSSNJNYLCGLOYCITVYQXPDIYFGEFYVXSXHKEGXKMMDSWBCYRKIZOCGMFDDTMWZTLSSFLJMOOLUUQJMIJSCIQVRUISTLTGNCLGKIKTZHRXENRXJHYZTLXICWWMYWXDYIBLERBFLWJQYWONGIQQCUUQTPPHBIEHTUVGCEGPEYMWICGKWJCUFKLUIDMJDIVPJDM"
    pred = replace(encode!(enigma, input2), " ", "")
    @assert pred == output

    enigma = get_M3_enigma('B', (3,5,8), "MCJ")
    output2 = "JFHJ"*"BXOD"*"IIZK"*"CHJU"*"TGOL"*"FIYX"*"RSLF"*"KKPO"*"JVRO"
    @assert encode!(enigma, input) == output2
    enigma = get_M3_enigma('B', (3,5,8), "MCJ")
    @assert encode!(enigma, output2) == input

    enigma = get_M3_enigma('C', (8,2,4), "PXM", "AB CY ET FQ HZ LG MJ OK US WX")
    output3 = "ULQC"*"XYXN"*"JMKV"*"FNAO"*"IVZS"*"OFTW"*"GQBB"*"XNWW"*"BIYS"
    @assert encode!(enigma, input) == output3
    enigma = get_M3_enigma('C', (8,2,4), "PXM", "AB CY ET FQ HZ LG MJ OK US WX")
    @assert encode!(enigma, output3) == input
end

max_stars_repo_name: MageekDM/Enigma

max_issues_repo_name: MageekDM/Enigma

max_forks_repo_name: MageekDM/Enigma


text:
#
# dialogs.jl -
#
# Wrappers for some Tk dialog widgets.
#

"""

```julia
Tcl.messagebox(interp=Tcl.getinterp(); parent="", title="", message="",
               detail="", icon="info", type="ok", default="", command="")
```

pops up a Tk message box dialog and returns the name of the selected button.
Tcl interpreter `interp` is used to run the dialog.  Available keywords are:

- Keyword `parent` specifies the window of the logical parent of the message box.
  The message box is displayed on top of its parent window.

- Keyword `title` specifies the title of the message box.  This option is
  ignored on Mac OS X, where platform guidelines forbid the use of a title on
  this kind of dialog.

- Keyword `message` specifies the message to display in this message box.  The
  default value is an empty string.

- Keyword `detail` specifies an auxiliary message to the main message.  The
  message detail will be presented beneath the main message and, where
  supported by the OS, in a less emphasized font than the main message.

- Keyword `icon` specifies an icon to display: `"error"`, `"info"`,
  `"question"` or `"warning"`.  By default, the `"info"` icon is displayed.

- Keyword `type` specifies which predefined set of buttons is displayed.
  The following values are possible:

  - `"abortretryignore"` to display three buttons whose symbolic names are
    `"abort"`, `"retry"` and `"ignore"`.

  - `"ok"` to display one button whose symbolic name is `"ok"`.

  - `"okcancel"` to display two buttons whose symbolic names are `"ok"` and
    `"cancel"`.

  - `"retrycancel"` to display two buttons whose symbolic names are `"retry"`
    and `"cancel"`.

  - `"yesno"` to display two buttons whose symbolic names are `"yes"` and
    `"no"`.

  - `"yesnocancel"` to display three buttons whose symbolic names are `"yes"`,
    `"no"` and `"cancel"`.

- Keyword `default` gives the name of the default button for this message
  window ( `"ok"`, `"cancel"`, and so on).  See keyword `type` for a list of
  the button names.  If this option is not specified, the first button in the
  dialog will be made the default.

- Keyword `command` specifies the prefix of a Tcl command to invoke when the
  user closes the dialog. The actual command consists of string followed by a
  space and the name of the button clicked by the user to close the dialog.
  This is only available on Mac OS X.

Example:

```julia
answer = Tcl.messagebox(message="Really quit?", icon="question", type="yesno",
                        detail="Select \"Yes\" to make the application exit")
if answer == "yes"
    quit()
elseif answer == "no"
    Tcl.messagebox(message="I know you like this application!",
                   type="ok")
end
```

See also [`Tcl.choosecolor`](@ref), [`Tcl.choosedirectory`](@ref),
[`Tcl.getopenfile`](@ref) and [`Tcl.getsavefile`](@ref).

"""
function messagebox(interp::TclInterp = getinterp();
                    parent::AbstractString = "",
                    title::AbstractString = "",
                    message::AbstractString = "",
                    detail::AbstractString = "",
                    icon::AbstractString = "",
                    type::AbstractString = "",
                    default::AbstractString = "",
                    command::AbstractString = "") :: String
    # Make sure Tk is loaded.
    tkstart(interp)

    # Build-up command.
    cmd = list("tk_messageBox")
    _push_dialog_option!(cmd, "-parent",  parent)
    _push_dialog_option!(cmd, "-title",   title)
    _push_dialog_option!(cmd, "-message", message)
    _push_dialog_option!(cmd, "-detail",  detail)
    _push_dialog_option!(cmd, "-icon",    icon)
    _push_dialog_option!(cmd, "-type",    type)
    _push_dialog_option!(cmd, "-default", default)
    _push_dialog_option!(cmd, "-command", command)

    # Evaluate command and return the result as a string.
    interp(String, cmd)
end

"""

```julia
Tcl.choosecolor(interp=Tcl.getinterp(); parent="", title="",
                initialcolor=nothing)
```

pops up a Tk dialog box for the user to select a color and returns the chosen
color as an instance of `TkRGB{UInt8}` or `nothing` if the user cancels the
dialog.  Tcl interpreter `interp` is used to run the dialog.  Available
keywords are:

- Keyword `parent` specifies the logical parent of the message box.  The color
  dialog box is displayed on top of its parent window.

- Keyword `title` specifies the title of the message box.

- Keyword `initialcolor` specifies the color to display in the color dialog
  when it pops up.  The value of this option can be a string like `"orange"` or
  `"#ff03ae"` or an instance of a sub-type of `TkColor`.

See also [`Tcl.choosedirectory`](@ref), [`Tcl.getopenfile`](@ref),
[`Tcl.getsavefile`](@ref) and [`Tcl.messagebox`](@ref).

"""
function choosecolor(interp::TclInterp = getinterp();
                     parent::AbstractString = "",
                     title::AbstractString = "",
                     initialcolor::Union{TkColor,AbstractString,Nothing} = nothing
                     ) :: Union{TkRGB{UInt8},Nothing}
    # Make sure Tk is loaded.
    tkstart(interp)

    # Build-up command.
    cmd = list("tk_chooseColor")
    _push_dialog_option!(cmd, "-parent",       parent)
    _push_dialog_option!(cmd, "-title",        title)
    _push_dialog_option!(cmd, "-initialcolor", initialcolor)

    # Evaluate command and return the result as a string.
    color = interp(String, cmd)
    if length(color) == 0
        return nothing
    elseif length(color) == 7 && color[1] == '#'
        return TkRGB{UInt8}(parse(UInt8, color[2:3], base=16),
                            parse(UInt8, color[4:4], base=16),
                            parse(UInt8, color[6:7], base=16))
    else
        error("unexpected color \"$color\"")
    end
end

"""

```julia
Tcl.choosedirectory(interp=Tcl.getinterp(); parent="", title="", message="",
                    initialdir="", mustexist=false, command="")
```

pops up a Tk dialog box for the user to select a directory and returns the
chosen directory name (an empty string if none).  Tcl interpreter `interp` is
used to run the dialog.  Available keywords are:

- Keyword `parent` specifies the window of the logical parent of the message box.
  The message box is displayed on top of its parent window.

- Keyword `title` specifies the title of the message box.  This option is
  ignored on Mac OS X, where platform guidelines forbid the use of a title on
  this kind of dialog.

- Keyword `message` specifies the message to display in this message box.  The
  default value is an empty string.  This is only available on Mac OS X.

- Keyword `initialdir` specifies that the directories in directory should be
  displayed when the dialog pops up.  If this parameter is not specified, the
  initial directory defaults to the current working directory on non-Windows
  systems and on Windows systems prior to Vista.  On Vista and later systems,
  the initial directory defaults to the last user-selected directory for the
  application. If the parameter specifies a relative path, the return value
  will convert the relative path to an absolute path.

- Keyword `mustexist` specifies whether the user may specify non-existent
  directories.  If this parameter is true, then the user may only select
  directories that already exist.

- Keyword `command` specifies the prefix of a Tcl command to invoke when the
  user closes the dialog. The actual command consists of string followed by a
  space and the name of the button clicked by the user to close the dialog.
  This is only available on Mac OS X.

See also [`Tcl.choosecolor`](@ref), [`Tcl.getopenfile`](@ref),
[`Tcl.getsavefile`](@ref) and [`Tcl.messagebox`](@ref).

"""
function choosedirectory(interp::TclInterp = getinterp();
                         parent::AbstractString = "",
                         title::AbstractString = "",
                         message::AbstractString = "",
                         initialdir::AbstractString = "",
                         mustexist::Bool = false,
                         command::AbstractString = "") :: String
    # Make sure Tk is loaded.
    tkstart(interp)

    # Build-up command.
    cmd = list("tk_chooseDirectory")
    _push_dialog_option!(cmd, "-parent",     parent)
    _push_dialog_option!(cmd, "-title",      title)
    _push_dialog_option!(cmd, "-initialdir", initialdir)
    _push_dialog_option!(cmd, "-mustexist",  mustexist)
    if Sys.isapple()
        _push_dialog_option!(cmd, "-message", message)
        _push_dialog_option!(cmd, "-command", command)
    end

    # Evaluate command and return the result as a string.
    interp(String, cmd)
end

"""

```julia
Tcl.getopenfile(interp=getinterp(); parent="", title="", message="",
                initialdir="", initialfile="", multiple=false,
                defaultextension="", filetypes="", typevariable="",
                command="")
```

or

```julia
Tcl.getsavefile(interp=getinterp(); parent="", title="", message="",
                initialdir="", initialfile="", confirmoverwrite=true,
                defaultextension="", filetypes="", typevariable="",
                command="")
```

pops up a Tk dialog box for the user to to select a file to open or save and
returns the name of the chosen file (an empty string if none).  Tcl interpreter
`interp` is used to run the dialog.  The following keywords are available:

- Keyword `parent` specifies the path of the logical parent of the file dialog.
  The file dialog is displayed on top of its parent window.  On Mac OS X, this
  turns the file dialog into a sheet attached to the parent window.

- Keyword `title` specifies a string to display as the title of the dialog box.
  If this option is not specified, then a default title is displayed.

- Keyword `message` Specifies a message to include in the client area of the
  dialog.  This is only available on Mac OS X.

- Keyword `initialdir` specifies the directory in which the files should be
  displayed when the dialog pops up.  If this parameter is not specified, the
  initial directory defaults to the current working directory on non-Windows
  systems and on Windows systems prior to Vista.  On Vista and later systems,
  the initial directory defaults to the last user-selected directory for the
  application. If the parameter specifies a relative path, the return value
  will convert the relative path to an absolute path.

- Keyword `initialfile` specifies a filename to be displayed in the dialog when
  it pops up.

- Keyword `multiple` specifies whether the user can choose multiple files from
  the Open dialog.  If multiple files are chosen, a vector of strings is
  returned.

- Keyword `confirmoverwrite` configures how the Save dialog reacts when the
  selected file already exists, and saving would overwrite it.  A true value
  requests a confirmation dialog be presented to the user.  A false value
  requests that the overwrite take place without confirmation.

- Keyword `defaultextension` specifies a string that will be appended to the
  filename if the user enters a filename without an extension.  The default
  value is the empty string, which means no extension will be appended to the
  filename in any case.  This option is ignored on Mac OS X, which does not
  require extensions to filenames, and the UNIX implementation guesses
  reasonable values for this from the `filetypes` option when this is not
  supplied.

- If a file types listbox exists in the file dialog on the particular platform,
  keyword `filetypes` gives the filetypes in this listbox.  When the user
  choose a filetype in the listbox, only the files of that type are listed.  If
  this option is unspecified, or if it is set to the empty list, or if the File
  types listbox is not supported by the particular platform then all files are
  listed regardless of their types.  See Tk manual for more details.

- Keyword `typevariable` specifies the name of a global Tcl variable used to
  preselect which filter is used from filterList when the dialog box is opened
  and is updated when the dialog box is closed, to the last selected
  filter. The variable is read once at the beginning to select the appropriate
  filter.  If the variable does not exist, or its value does not match any
  filter typename, or is empty ({}), the dialog box will revert to the default
  behavior of selecting the first filter in the list. If the dialog is
  canceled, the variable is not modified.

- Keyword `command` specifies the prefix of a Tcl command to invoke when the
  user closes the dialog after having selected an item.  This callback is not
  called if the user cancelled the dialog.  The actual command consists of the
  `command` string followed by a space and the value selected by the user in
  the dialog.  This is only available on Mac OS X.

See also [`Tcl.choosecolor`](@ref), [`Tcl.choosedirectory`](@ref) and
[`Tcl.messagebox`](@ref).

"""
function getopenfile(interp::TclInterp = getinterp();
                     parent::AbstractString = "",
                     title::AbstractString = "",
                     message::AbstractString = "",
                     initialdir::AbstractString = "",
                     initialfile::AbstractString = "",
                     multiple::Bool = false,
                     defaultextension::AbstractString = "",
                     filetypes::AbstractString = "",
                     typevariable::AbstractString = "",
                     command::AbstractString = "") :: Union{String,Vector{String}}
    # Make sure Tk is loaded.
    tkstart(interp)

    # Build-up command.
    cmd = list("tk_getOpenFile", "-multiple", multiple)
    _push_dialog_option!(cmd, "-parent",           parent)
    _push_dialog_option!(cmd, "-title",            title)
    _push_dialog_option!(cmd, "-initialdir",       initialdir)
    _push_dialog_option!(cmd, "-initialfile",      initialfile)
    _push_dialog_option!(cmd, "-defaultextension", defaultextension)
    _push_dialog_option!(cmd, "-filetypes",        filetypes)
    _push_dialog_option!(cmd, "-typevariable",     typevariable)
    if Sys.isapple()
        _push_dialog_option!(cmd, "-message", message)
        _push_dialog_option!(cmd, "-command", command)
    end

    # Evaluate command and return the result as a string or a vector of string.
    interp(cmd)
end

function getsavefile(interp::TclInterp = getinterp();
                     parent::AbstractString = "",
                     title::AbstractString = "",
                     message::AbstractString = "",
                     initialdir::AbstractString = "",
                     initialfile::AbstractString = "",
                     confirmoverwrite::Bool = true,
                     defaultextension::AbstractString = "",
                     filetypes::AbstractString = "",
                     typevariable::AbstractString = "",
                     command::AbstractString = "") :: String
    # Make sure Tk is loaded.
    tkstart(interp)

    # Build-up command.
    cmd = list("tk_getSaveFile", "-confirmoverwrite", confirmoverwrite)
    _push_dialog_option!(cmd, "-parent",           parent)
    _push_dialog_option!(cmd, "-title",            title)
    _push_dialog_option!(cmd, "-initialdir",       initialdir)
    _push_dialog_option!(cmd, "-initialfile",      initialfile)
    _push_dialog_option!(cmd, "-defaultextension", defaultextension)
    _push_dialog_option!(cmd, "-filetypes",        filetypes)
    _push_dialog_option!(cmd, "-typevariable",     typevariable)
    if Sys.isapple()
        _push_dialog_option!(cmd, "-message", message)
        _push_dialog_option!(cmd, "-command", command)
    end

    # Evaluate command and return the result as a string.
    interp(String, cmd)
end

@doc @doc(getopenfile) getsavefile

# Append a string-valued option (nothing if the value is an empty string).
_push_dialog_option!(cmd::TclObj{<:Vector}, opt::AbstractString, val::String) =
    length(val) > 0 && lappend!(cmd, opt, val)

# Append a boolean-valued option.
_push_dialog_option!(cmd::TclObj{<:Vector}, opt::AbstractString, val::Bool) =
    lappend!(cmd, opt, (val ? "true" : "false"))

# Append an unspecified option.
_push_dialog_option!(cmd::TclObj{<:Vector}, opt::AbstractString, val::Nothing) =
    nothing

# Append a color.
_push_dialog_option!(cmd::TclObj{<:Vector}, opt::AbstractString, val::TkColor) =
    lappend!(cmd, opt, repr(val))


text:
function trapezoid_rule(a,b,N)
    w=Array(Float64,(N+1,));
    x=linspace(a,b,N+1);
    w[1]=1.0;
    w[2:N]=2.0;
    w[N+1]=1.0;
    w[:]=w*((b-a)/(2*N));
    return (x,w);
end

function trapezoid_tensor_product(a,b,N)
    (x,w)=trapezoid_rule(a,b,N);
    y=copy(x);
    z=copy(x);
    W=Array(Float64,(N+1,N+1,N+1));
    for i = 1 : length(w)
        for j = 1 : length(w)
            for k = 1 : length(w)
                W[i,j,k]=w[i]*w[j]*w[k];
            end
        end
    end
    return (x,y,z,W);
end

max_stars_repo_name: ReidAtcheson/incns

max_issues_repo_name: ReidAtcheson/incns

max_forks_repo_name: ReidAtcheson/incns


text:
function isapprox_discrete(com::CS.CoM, val)
    return isapprox(val, round(val); atol = com.options.atol, rtol = com.options.rtol)
end

function isapprox_divisible(com::CS.CoM, val, divider)
    modulo_near_0 =
        isapprox(val % divider, 0; atol = com.options.atol, rtol = com.options.rtol)
    modulo_near_divider =
        isapprox(val % divider, divider; atol = com.options.atol, rtol = com.options.rtol)
    return modulo_near_0 || modulo_near_divider
end

function get_approx_discrete(val)
    return convert(Int, round(val))
end

function get_safe_upper_threshold(com::CS.CoM, val, divider)
    float_threshold = val / divider
    floor_threshold = floor(float_threshold)
    threshold = convert(Int, floor_threshold)
    # if the difference is almost 1 we round in the other direction to provide a safe upper bound
    if isapprox(
        float_threshold - floor_threshold,
        1.0;
        rtol = com.options.rtol,
        atol = com.options.atol,
    )
        threshold += 1
    end
    return threshold
end

function get_safe_lower_threshold(com::CS.CoM, val, divider)
    float_threshold = val / divider
    ceil_threshold = ceil(float_threshold)
    threshold = convert(Int, ceil_threshold)
    # if the difference is almost 1 we round in the other direction to provide a safe lower bound
    if isapprox(
        ceil_threshold - float_threshold,
        1.0;
        rtol = com.options.rtol,
        atol = com.options.atol,
    )
        threshold -= 1
    end
    return threshold
end

"""
    fixed_vs_unfixed(search_space, indices)

Return the fixed_vals as well as the unfixed_indices
"""
function fixed_vs_unfixed(search_space, indices)
    # get all values which are fixed
    fixed_vals = Int[]
    unfixed_indices = Int[]
    for (i, vidx) in enumerate(indices)
        if isfixed(search_space[vidx])
            push!(fixed_vals, CS.value(search_space[vidx]))
        else
            push!(unfixed_indices, i)
        end
    end
    return (fixed_vals, unfixed_indices)
end

"""
    update_table_log(com::CS.CoM, backtrack_vec; force=false)

Push the new information to the TableLogger and if `force` produce a new line otherwise the TableLogger decides
"""
function update_table_log(com::CS.CoM, backtrack_vec; force = false)
    table = com.options.table
    open_nodes = count(n -> n.status == :Open, backtrack_vec)
    # -1 for dummy node
    closed_nodes = length(backtrack_vec) - open_nodes - 1
    best_bound = com.best_bound
    incumbent = length(com.solutions) == 0 ? "-" : com.best_sol
    duration = time() - com.start_time
    push_to_table!(
        table;
        force = force,
        open_nodes = open_nodes,
        closed_nodes = closed_nodes,
        incumbent = incumbent,
        best_bound = best_bound,
        duration = duration,
    )
end

"""
    arr2dict(arr)

Return a boolean dictionary with keys as the value of the array and `true` if the value exists
"""
function arr2dict(arr)
    d = Dict{Int,Bool}()
    for v in arr
        d[v] = true
    end
    return d
end

function is_constraint_solved(com::CS.CoM, constraint::Constraint, fct, set)
    variables = com.search_space
    !all(isfixed(variables[ind]) for ind in constraint.indices) && return false
    values = CS.value.(variables[constraint.indices])
    return is_constraint_solved(constraint, fct, set, values)
end

function is_constraint_solved_when_fixed(com::CS.CoM, constraint::Constraint, fct, set, vidx::Int, value::Int)
    variables = com.search_space
    !all(isfixed(variables[ind]) || variables[ind].idx == vidx for ind in constraint.indices) && return false
    values = zeros(Int, length(constraint.indices))
    for (i,ind) in enumerate(constraint.indices)
        if ind != vidx
            values[i] = CS.value(variables[ind])
        else
            values[i] = value
        end
    end
    return is_constraint_solved(constraint, fct, set, values)
end

#=
    Access standard ConstraintInternals without using .std syntax
=#
@inline function Base.getproperty(c::Constraint, s::Symbol)
    if s in (
        :idx,
        :indices,
        :fct,
        :set,
        :pvals,
        :is_initialized,
        :is_activated,
        :is_deactivated,
        :bound_rhs,
    )
        Core.getproperty(Core.getproperty(c, :std), s)
    else
        getfield(c, s)
    end
end

@inline function Base.setproperty!(c::Constraint, s::Symbol, v)
    if s in (
        :idx,
        :indices,
        :fct,
        :set,
        :pvals,
        :is_initialized,
        :is_activated,
        :is_deactivated,
        :bound_rhs,
    )
        Core.setproperty!(c.std, s, v)
    else
        Core.setproperty!(c, s, v)
    end
end

#=
    Access standard ActivatorConstraintInternals without using .act_std syntax
=#
@inline function Base.getproperty(c::ActivatorConstraint, s::Symbol)
    if s in (
        :idx,
        :indices,
        :fct,
        :set,
        :pvals,
        :is_initialized,
        :is_activated,
        :is_deactivated,
        :bound_rhs,
    )
        Core.getproperty(Core.getproperty(c, :std), s)
    elseif s in (
        :activate_on,
        :activator_in_inner,
        :inner_activated,
        :inner_activated_in_backtrack_idx,
    )
        Core.getproperty(Core.getproperty(c, :act_std), s)
    else
        getfield(c, s)
    end
end

@inline function Base.setproperty!(c::ActivatorConstraint, s::Symbol, v)
    if s in (
        :idx,
        :indices,
        :fct,
        :set,
        :pvals,
        :is_initialized,
        :is_activated,
        :is_deactivated,
        :bound_rhs,
    )
        Core.setproperty!(c.std, s, v)
    elseif s in (
        :activate_on,
        :activator_in_inner,
        :inner_activated,
        :inner_activated_in_backtrack_idx,
    )
        Core.setproperty!(c.act_std, s, v)
    else
        Core.setproperty!(c, s, v)
    end
end

#=
    Access standard BoolConstraintInternals without using .bool_std syntax
=#
@inline function Base.getproperty(c::BoolConstraint, s::Symbol)
    if s in (
        :idx,
        :indices,
        :fct,
        :set,
        :pvals,
        :is_initialized,
        :is_activated,
        :is_deactivated,
        :bound_rhs,
    )
        Core.getproperty(Core.getproperty(c, :std), s)
    elseif s in (
        :lhs_activated,
        :lhs_activated_in_backtrack_idx,
        :rhs_activated,
        :rhs_activated_in_backtrack_idx,
        :lhs,
        :rhs
    )
        Core.getproperty(Core.getproperty(c, :bool_std), s)
    else
        getfield(c, s)
    end
end

@inline function Base.setproperty!(c::BoolConstraint, s::Symbol, v)
    if s in (
        :idx,
        :indices,
        :fct,
        :set,
        :pvals,
        :is_initialized,
        :is_activated,
        :is_deactivated,
        :bound_rhs,
    )
        Core.setproperty!(c.std, s, v)
    elseif s in (
        :lhs_activated,
        :lhs_activated_in_backtrack_idx,
        :rhs_activated,
        :rhs_activated_in_backtrack_idx,
        :lhs,
        :rhs
    )
        Core.setproperty!(c.bool_std, s, v)
    else
        Core.setproperty!(c, s, v)
    end
end

@inline function Base.getproperty(c::AbstractBoolSet, s::Symbol)
    if s in (
        :lhs_set,
        :rhs_set,
        :lhs_dimension,
        :rhs_dimension,
        :dimension,
    )
        Core.getproperty(Core.getproperty(c, :bsi), s)
    else
        getfield(c, s)
    end
end

"""
    Return whether the given LinearConstraint doesn't contain any variables i.e for 0 <= 0
"""
function is_no_variable_constraint(constraint::LinearConstraint)
    return length(constraint.indices) == 0
end

get_value(::Type{Val{i}}) where i = i

for bool_pair = BOOL_SET_TO_CONSTRAINT
    bool_set = bool_pair.first
    @eval typeof_without_params(::$bool_set) = $bool_set
    @eval typeof_without_params(::Type{<:$bool_set}) = $bool_set
end

function get_constraint(com, fct, set)
    if fct isa SAF
        return get_linear_constraint(fct, set)
    else
        internals = create_internals(fct, set)
        return init_constraint_struct(com, set, internals)
    end
end

get_saf(fct::MOI.ScalarAffineFunction) = fct
get_saf(fct::MOI.VectorAffineFunction) = MOI.ScalarAffineFunction([t.scalar_term for t in fct.terms], fct.constants[1])

get_vov(fct::MOI.VectorOfVariables) = fct
get_vov(fct::MOI.VectorAffineFunction) = MOI.VectorOfVariables([t.scalar_term.variable_index for t in fct.terms])

"""
    init_and_activate_constraint!(com, constraint, fct, set)

Initializes and activates the constraint. Does **not** check whether the functions are implemented.
"""
function init_and_activate_constraint!(
    com::CS.CoM,
    constraint::Constraint,
    fct,
    set
)
    !init_constraint!(com, constraint, fct, set) && return false
    constraint.is_initialized = true
    !activate_constraint!(com, constraint, fct, set) && return false
    constraint.is_activated = true
    return true
end

"""
    push_to_changes!(v::Variable, tuple::Tuple{Symbol,Int,Int,Int})

Push a new change to the variable `v`.
"""
function push_to_changes!(v::Variable, tuple::Tuple{Symbol,Int,Int,Int})
    v.changes.indices[end] += 1
    push!(v.changes.changes, tuple)
    @assert v.changes.indices[end]-1 == length(v.changes.changes)
end

"""
    num_changes(v::Variable, step_nr::Int)

Return the number of changes that were done for `v` in `step_nr`.
"""
function num_changes(v::Variable, step_nr::Int)
    return v.changes.indices[step_nr+1] - v.changes.indices[step_nr]
end

"""
    view_changes(v::Variable, step_nr::Int)

Return a view of the changes made for `v` in `step_nr`
"""
function view_changes(v::Variable, step_nr::Int)
    idx_begin = v.changes.indices[step_nr]
    idx_end = v.changes.indices[step_nr+1]-1
    return @views v.changes.changes[idx_begin:idx_end]
end

function changed!(com::CS.CoM, constraint::Constraint, fct, set)
    return
end


text:
function c2x!(ψ::Array{Complex{Float64},1},c::Array{Complex{Float64},1},tinfo::ProjectedGPE.Tinfo)
    ψ = tinfo.Tx*c
end

function c2x!(ψ::Array{Complex{Float64},2},c::Array{Complex{Float64},2},tinfo::ProjectedGPE.Tinfo)
    ψ .= tinfo.Tx*c*tinfo.Ty'
end

function c2x!(ψ::Array{Complex{Float64},3},c::Array{Complex{Float64},3},tinfo::ProjectedGPE.Tinfo)
    sa = size(c);sx = size(tinfo.Tx);sy = size(tinfo.Ty);sz = size(tinfo.Tz)
    acyc = (2,3,1)
    Ax = reshape(c,(sa[1],sa[2]*sa[3]))
    Ax = reshape(tinfo.Tx*Ax,(sx[1],sa[2],sa[3]))
    Ax = permutedims(Ax,acyc);sa = size(Ax)

    Ay = reshape(Ax,(sa[1],sa[2]*sa[3]))
    Ay = reshape(tinfo.Ty*Ay,(sy[1],sa[2],sa[3]))
    Ay = permutedims(Ay,acyc);sa = size(Ay)

    Az = reshape(Ay,(sa[1],sa[2]*sa[3]))
    Az = reshape(tinfo.Tz*Az,(sz[1],sa[2],sa[3]))
    ψ = permutedims(Az,acyc)
end


text:
using Statistics
using ProgressMeter
using MATLAB
include("atn_module.jl")

N = 10_000          # number of nodes
m = 5               # number of active links per active node
mu = 0.1            # probability I -> S
tmax = 3000         # maximum duration of the simulation
Ni = Int(0.01 * N)  # initial number of infects
gamma = -2.1      # exponent of the power law
NTrials = 1       # number of trials for each value of lambda
TWindow = 500.0      # time window for evaluating steady state
TMinConvergence = 500

LambdaMin = 0.0
LambdaMax = 1.0
LambdaStep = 0.05
Lambda = LambdaMin:LambdaStep:LambdaMax
LambdaSize = length(Lambda)

EtaMin = 0.0
EtaMax = 15
EtaStep = 0.5
Eta = EtaMin:EtaStep:EtaMax
EtaSize = length(Eta)
AvgInfectedLambda = zeros(LambdaSize)
Ni = Int(0.01 * N)  # initial number of infects
gamma = -2.1       # exponent of the power law
TWindow = 500       # time window for evaluating steady state
TMinConvergence = 500
ITrend = zeros(Int, 0)
ActMin = 0.001      # minimum activation probability
ActMax = 1
AgentAct = ((ActMax .^ (gamma + 1) - ActMin .^ (gamma + 1)) .* rand(N) .+
            ActMin .^ (gamma + 1)) .^ (1.0 / (gamma + 1))
# AvgDegree = 2 * m * mean(AgentAct)
# AgentState = zeros(Bool, N)
# AgentState[1:Ni] .= 1
etaS = 15
eta = 1

lambda = 0.5
InfectedOverTrials = zeros(0)
InfectedOverATrial = zeros(0)
Activitylist = zeros(0)
for nt in 1:NTrials
    AgentState = zeros(Bool, N)
    AgentState[1:Int(0.01 * N)] .= 1
    InfectedOverATrial = 0.0
    for i_time in 1:tmax
        AgentStateNext = AgentState
        for i in 1:N
            if AgentState[i] == 1
                r = rand()
                if (r < mu)
                    AgentStateNext[i] = 0
                r = rand()
                if (r < mu)
            Activity = AgentState[i]
            push!(Activitylist, Activity)
            r = rand()
            if (Activity > r)
                for j in 1:m
                    rInt = rand(1:N)
                    if (AgentState[i] == 1)
                        r = rand()
                        if ((AgentState[rInt] == 0) && (r < lambda))
                    if (AgentState[i] == 1)
                        r = rand()
                        if ((AgentState[rInt] == 0) && (r < lambda))
                            # println(rInt)
                            AgentStateNext[rInt] = 1
                        end
                    else
                        r = rand()
                        if ((AgentState[rInt] == 1) && (r < lambda))
                            # println(rInt)
                end
            end
        end
        NumInf = 0
        for k in 1:N
            AgentState[k] = AgentStateNext[k]
            if (AgentState[k] == 1)
                NumInf = NumInf + 1
            endntState[k] = AgentStateNext[k]
            if (AgentState[k] == 1)
                NumInf = NumInf + 1
            end
        end
        push!(InfectedOverTrials, NumInf)
    end
    # InfectedOverATrial = InfectedOverATrial / TWindow
    # push!(InfectedOverTrials, InfectedOverATrial)
end

# println(sum(InfectedOverTrials) / NTrials)
# AvgInfectedLambda[ilambda] = InfectedOverTrials / NTrials
# end
# end
# AvgInfectedEtaLambda = Float64.(transpose(AvgInfectedEtaLambda))
# mat"figure();set(gcf, 'Position',  [0, 0, 2500, 1500]); hold on;"
# mat"axis([ -0,1,-0,10 ])"
# mat"imagesc([0,1],[0,10],$AvgInfectedEtaLambda)"
# mat"colormap jet"
# location_mat = "/mnt/storage/MAT/"
# right_now = replace(
#     replace(replace(string(Dates.now()), "." => "_"), ":" => "_"),
#     "-" => "_",
# )

# file_name = "practice" * right_now
# mat_name = location_mat * file_name * ".mat"
#
# matwrite(
#     mat_name,
#     Dict("AvgInfectedLambda" => AvgInfectedLambda);
#     compress = true,
# )
# AvgInfectedEtaLambda = Float64.(transpose(AvgInfectedEtaLambda))
mat"figure();set(gcf, 'Position',  [0, 0, 2500, 1500]); hold on;"
# # mat"axis([ -0,1,-0,10 ])"
# # mat"imagesc([0,1],[0,10],$AvgInfectedEtaLambda)"
# # mat"colormap jet"
#
mat"plot(1:3000,$InfectedOverTrials,'.-','MarkerSize',20)"


text:
@testset "146.lru-cache.jl" begin
    cache = LRUCache(2)
    cache[1] = 1
    cache[2] = 2
    @test cache[1] == 1
    cache[3] = 3
    @test cache[2] == -1
    cache[4] = 4
    @test cache[1] == -1
    @test cache[3] == 3
    @test cache[4] == 4
    cache[4] = 2
    @test cache[4] == 2
end


text:
include("helpingfunctions.jl")
outfile = "streamlines.csv"
infilename = "jc.csv"
numberOfLines = 50

data =  initialize(infilename, numberOfLines)

J = solve(data)
println("I am done with computing the streamlines,
but I have to write the data to file.")

writecsv(outfile, float(J))
print("I am done with everything. Data stored in "
 * string(outfile) )

max_stars_repo_name: knuttyse/BeanStreamlines

max_issues_repo_name: knuttyse/BeanStreamlines

max_forks_repo_name: knuttyse/BeanStreamlines


text:
"""
    Drawing

Overarching type for objects displayable on `Axes`.
"""
abstract type Drawing end

"""
    Drawing

Overarching type for objects displayable on `Axes2D`.
"""
abstract type Drawing2D <: Drawing end

"""
    Drawing

Overarching type for objects displayable on `Axes3D`.
"""
abstract type Drawing3D <: Drawing end

"""
    DrawingHandle{D<:Drawing}

Container object for a drawing returned by any plotting function.
"""
struct DrawingHandle{D<:Drawing}
    drawing::D
end

"""
    Scatter2D <: Drawing2D

2D Line plot(s) or scatter plot(s). See also [`plot!`](@ref), [`line!`](@ref) and
[`scatter!`](@ref).
"""
mutable struct Scatter2D{T} <: Drawing2D
    data        ::T                   # data container (zip; T = trick to avoid failure on 1.0)
    hasmissing  ::Bool                # whether there are missing|inf|nan data
    nobj        ::Int                 # number of objects
    linestyles  ::Vector{LineStyle}   # line style (color, width, ...)
    markerstyles::Vector{MarkerStyle} # marker style (color, size, ...)
    labels      ::Vector{String}      # plot labels (to go in the legend)
end

"""
    $SIGNATURES

Internal constructor for Scatter2D object adding linestyles, markerstyles and labels.
"""
Scatter2D(d, m, n) = Scatter2D(d, m, n, nvec(n, LineStyle), nvec(n, MarkerStyle), String[])

"""
    Fill2D <: Drawing2D

Fill-plot between two 2D curves. Missing values are not allowed. See [`fill_between!`](@ref).
"""
@with_kw mutable struct Fill2D{T} <: Drawing2D
    data     ::T  # data iterator
    #
    xmin     ::Option{Float64} = ∅           # left most anchor
    xmax     ::Option{Float64} = ∅           # right most anchor
    fillstyle::FillStyle       = FillStyle() # describes the area between the curves
    label    ::String          = ""
end

"""
    Hist2D <: Drawing2D

Histogram.
"""
@with_kw mutable struct Hist2D{T} <: Drawing2D
    data      ::T     # data container
    hasmissing::Bool  # whether has missing|inf|nan data
    nobs      ::Int   # number of non-missing entries
    range     ::T2F   # (minvalue, maxvalue)
    #
    barstyle::BarStyle    = BarStyle() #
    horiz   ::Bool        = false      # horizontal histogram?
    bins    ::Option{Int} = ∅          # number of bins
    scaling ::String      = "none"     # scaling (pdf, count=none, probability)
    label   ::String      = ""
end

"""
    Bar2D <: Drawing2D

Bar plot(s).
"""
@with_kw mutable struct Bar2D{T} <: Drawing2D
    data      ::T               # data container
    hasmissing::Bool            # whether has missing|inf|nan
    nobj      ::Int
    barstyles ::Vector{BarStyle}
    #
    stacked::Bool            = false
    horiz  ::Bool            = false
    bwidth ::Option{Float64} = ∅ # general bar width
    #
    labels ::Vector{String}  = String[]
end

"""
    Bar2D(data, hasmissing, nobj)

Internal constructor for Bar2D object adding barstyles.
"""
Bar2D(d, m, n) = Bar2D(data=d, hasmissing=m, nobj=n, barstyles=nvec(n, BarStyle))


text:
module NonDet

using Spec
using DocStringExtensions

using ..IDS
using ..Space
import ..Space: Ω, ΩBase, ΩProj, TaggedΩ, Tags, defΩ, hastags, base, tag, parentω
import ..Omega

include("nondetvar.jl")        # Non deterministic variable
include("var.jl")              # Free variable
include("randvar.jl" )         # Random variables
include("urandvar.jl")         # Random variables
include("randvarapply.jl")     # Random variable application to ω::Ω
include("ciid.jl")             # Conditionally i.i.d. NonDet
include("elemtype.jl")         # Infer Element Type
include("memoize.jl")          # Infer Element Type

export NonDetVar
export Var
export mem
export unit, solve, optim
export RandVar, MaybeRV, ciid, isconstant, elemtype, params, constant, apl

end


text:
module TestEllipsisNotationCompat # use a module to avoid cluttering the global namespace

using EllipsisNotation
using HybridArrays
using Test

if VERSION >= v"1.5"
  @testset "Compatibility with EllipsisNotation" begin
    u_array  = rand(2, 10)
    u_hybrid = HybridArray{Tuple{2, HybridArrays.Dynamic()}}(copy(u_array))
    @test u_hybrid        ≈ u_array
    @test u_hybrid[1, ..] ≈ u_array[1, ..]
    @test u_hybrid[.., 1] ≈ u_array[.., 1]
    @test u_hybrid[..]    ≈ u_array[..]

    @test typeof(u_hybrid[1, ..]) == typeof(u_hybrid[1, :])
    @test typeof(u_hybrid[.., 1]) == typeof(u_hybrid[:, 1])
    @test typeof(u_hybrid[..])    == typeof(u_hybrid[:])
    @test typeof(u_hybrid[..,..]) == typeof(u_hybrid[:, :])

    @inferred u_hybrid[1, ..]
    @inferred u_hybrid[.., 1]
    @inferred u_hybrid[..]

    let new_values = rand(10)
      u_array[1, ..]  .= new_values
      u_hybrid[1, ..] .= new_values
      @test u_hybrid        ≈ u_array
      @test u_hybrid[1, ..] ≈ u_array[1, ..]
      @test u_hybrid[.., 1] ≈ u_array[.., 1]
      @test u_hybrid[..]    ≈ u_array[..]
    end

    let new_values = rand(2)
      u_array[.., 1]  .= new_values
      u_hybrid[.., 1] .= new_values
      @test u_hybrid        ≈ u_array
      @test u_hybrid[1, ..] ≈ u_array[1, ..]
      @test u_hybrid[.., 1] ≈ u_array[.., 1]
      @test u_hybrid[..]    ≈ u_array[..]
    end

    let new_values = rand(2, 10)
      u_array  .= new_values
      u_hybrid .= new_values
      @test u_hybrid        ≈ u_array
      @test u_hybrid[1, ..] ≈ u_array[1, ..]
      @test u_hybrid[.., 1] ≈ u_array[.., 1]
      @test u_hybrid[..]    ≈ u_array[..]
    end
  end
end

@testset "Compatibility with Cartesian indices" begin
  u_array  = rand(2, 3, 4)
  u_hybrid = HybridArray{Tuple{2, 3, 4}}(copy(u_array))
  @test u_hybrid        ≈ u_array
  @test u_hybrid[CartesianIndex(1, 2), :] ≈ u_array[CartesianIndex(1, 2), :]
  @test u_hybrid[:, CartesianIndex(1, 2)] ≈ u_array[:, CartesianIndex(1, 2)]

  @test typeof(u_hybrid[CartesianIndex(1, 2), :]) == typeof(u_hybrid[1, 2, :])
  @test typeof(u_hybrid[:, CartesianIndex(1, 2)]) == typeof(u_hybrid[:, 1, 2])

  @inferred u_hybrid[CartesianIndex(1, 2), :]
  @inferred u_hybrid[:, CartesianIndex(1, 2)]
  @inferred u_hybrid[CartesianIndex(1, 2, 3)]

  let new_values = rand(4)
    u_array[CartesianIndex(1, 2), :]  .= new_values
    u_hybrid[CartesianIndex(1, 2), :] .= new_values
    @test u_hybrid        ≈ u_array
    @test u_hybrid[CartesianIndex(1, 2), :] ≈ u_array[CartesianIndex(1, 2), :]
    @test u_hybrid[:, CartesianIndex(1, 2)] ≈ u_array[:, CartesianIndex(1, 2)]
  end

  let new_values = rand(2)
    u_array[:, CartesianIndex(1, 2)]  .= new_values
    u_hybrid[:, CartesianIndex(1, 2)] .= new_values
    @test u_hybrid        ≈ u_array
    @test u_hybrid[CartesianIndex(1, 2), :] ≈ u_array[CartesianIndex(1, 2), :]
    @test u_hybrid[:, CartesianIndex(1, 2)] ≈ u_array[:, CartesianIndex(1, 2)]
  end
end

end # module


text:
using Documenter, ITensors

DocMeta.setdocmeta!(ITensors, :DocTestSetup, :(using ITensors); recursive=true)

sitename = "ITensors.jl"

settings = Dict(
  :modules => [ITensors],
  :pages => [
    "Introduction" => "index.md",
    "Getting Started with ITensor" => [
      "Installing Julia and ITensor" => "getting_started/Installing.md",
      "Running ITensor and Julia Codes" => "getting_started/RunningCodes.md",
      "Tutorials" => "getting_started/Tutorials.md",
      "Next Steps" => "getting_started/NextSteps.md",
    ],
    "Code Examples" => [
      "ITensor Examples" => "examples/ITensor.md",
      "MPS and MPO Examples" => "examples/MPSandMPO.md",
      "DMRG Examples" => "examples/DMRG.md",
      "Physics System Examples" => "examples/Physics.md",
    ],
    "Documentation" => [
      "Index" => "IndexType.md",
      "IndexVal" => "IndexValType.md",
      "IndexSet" => "IndexSetType.md",
      "ITensor" => "ITensorType.md",
      "MPS and MPO" => "MPSandMPO.md",
      "QN" => "QN.md",
      "SiteType and op" => "SiteType.md",
      "DMRG" => [
        "DMRG.md",
        "Sweeps.md",
        "ProjMPO.md",
        "ProjMPOSum.md",
        "Observer.md",
        "DMRGObserver.md",
      ],
      "AutoMPO" => "AutoMPO.md",
    ],
    "Advanced usage guide" => [
      "Advanced usage guide" => "AdvancedUsageGuide.md",
      "Multithreading" => "Multithreading.md",
      "Symmetric tensor background and usage" => "QNTricks.md",
      "Timing and profiling" => "CodeTiming.md",
      "Contraction sequence optimization" => "ContractionSequenceOptimization.md",
    ],
  ],
  :format => Documenter.HTML(; assets=["assets/favicon.ico"], prettyurls=false),
  :doctest => true,
  :checkdocs => :none,
)


text:
const DATA = read("day06.txt", String)
const groups = split(DATA, "\n\n")

function part1(groups::Vector{<:AbstractString})
    total = 0
    for group in groups
        yes = Set(replace(group, '\n' => ""))
	total += length(yes)
    end
    return total
end

println("Part1: $(part1(groups))")

function part2(groups::Vector{<:AbstractString})
    total = 0
    for group in groups
    	yes = reduce(intersect, split(group, '\n'))
	total += length(yes)
    end
    return total
end

println("Part2: $(part2(groups))")


text:
module StringDistances

using Distances: Distances, SemiMetric, Metric, evaluate, result_type
using StatsAPI: StatsAPI, pairwise, pairwise!
# Distances API
abstract type StringSemiMetric <: SemiMetric end
abstract type StringMetric <: Metric end
const StringDistance = Union{StringSemiMetric, StringMetric}
function Distances.result_type(dist::Union{StringSemiMetric, StringMetric}, s1::Type, s2::Type)
    T = typeof(dist("", ""))
    if (Missing <: s1) | (Missing <: s2)
        T = Union{T, Missing}
    end
    return T
end
Distances.result_type(dist::Union{StringSemiMetric, StringMetric}, s1, s2) = result_type(dist, typeof(s1), typeof(s2))

(dist::Union{StringSemiMetric, StringMetric})(s1, s2; max_dist = nothing) = dist(s1, s2)
include("utils.jl")
include("distances/edit.jl")
include("distances/qgram.jl")
include("pairwise.jl")
include("normalize.jl")
include("find.jl")
include("fuzzywuzzy.jl")

##############################################################################
##
## Export
##
##############################################################################

export
StringDistance,
StringSemiMetric,
StringMetric,
# edit distances
Hamming,
Jaro,
JaroWinkler,
Levenshtein,
OptimalStringAlignment,
DamerauLevenshtein,
RatcliffObershelp,
# Qgram distances
AbstractQGramDistance,
QGramDict,
QGramSortedVector,
QGram,
Cosine,
Jaccard,
SorensenDice,
Overlap,
MorisitaOverlap,
NMD,
qgrams,
# normalize
compare,
# fuzzywuzzy
Partial,
TokenSort,
TokenSet,
TokenMax,
# find
findnearest,
# re-rexport from Distances.jl
evaluate,
result_type,
pairwise,
pairwise!
end

max_stars_repo_name: matthieugomez/StringDistances

max_issues_repo_name: matthieugomez/StringDistances

max_forks_repo_name: matthieugomez/StringDistances


text:
using SuffixTrees, Test

tests = [
    ("CAAAABAAAABD\$", "AAAAB"),
    ("GEEKSFORGEEKS\$", "GEEKS"),
    ("AAAAAAAAAA\$", "AAAAAAAAA"),
    ("ABCDEFG\$", ""),
    ("ABABABA\$", "ABABA"),
    ("ATCGATCGA\$", "ATCGA"),
    ("banana\$", "ana"),
    ("abcpqrabpqpq\$", "ab (or) pq"),
    ("pqrpqpqabab\$", "ab (or) pq"),
]
println("Longest Repeated Substring in:\n")
for (test, ans) in tests
    st = SuffixTree(test)
    @test getlongestrepeatedsubstring(st) == ans
end


text:
using ForestFire
using Test

@testset "ForestFire.jl" begin
    # Tests
end

max_stars_repo_name: TheSquareRoot/ForestFire

max_issues_repo_name: TheSquareRoot/ForestFire

max_forks_repo_name: TheSquareRoot/ForestFire