:Namespace phase2 ⍝ -*- mode:dyalog -*-

 ⍝ ⎕IO=1 is assumed throughout these solutions.

 ⍝ Dyalog 18.0 is used.

    ⎕IO←1

 ⍝ Q1 subspace journey

 ⍝ FIXME: Please specify which filling index to use

 ⍝    when the regions overlap in T2.

 ⍝ In T3, "in the range 1-≢subspaces" looks confusing, could

 ⍝    replace it with "⍳≢subspaces" or just plain English "from

 ⍝    1 to ≢subspaces".



 ⍝ My first attempt for Task 1 is using  ⊤

 ⍝ note that:  a runs 1 2⍴b 1  is  ⌽(a⍴2)⊤2*b-1


 ⍝ first to compute the numbers

    num←{⎕IO←0 ⋄ 2*¯1+(⊣/⍵)+⍳⊢/⍵}


      runs←{

          ⍝ each  is just a name for

          ⍝ inner loop

          each←⌽⍤(+/(⍺⍴2)⊤num)

          ∨⌿⍺ each⍤1⊢⍵

      }


 ⍝ For Task 2,  ∘.∧  is used.

      fill←{

          size←⍺

          rank←≢size

          reshap←⍉(2 rank)∘⍴

          run←{⌽+/(⍺⍴2)⊤num ⍵} ⍝ Rewrite of T1

          each←{⊃∘.∧/size run¨↓reshap ⍵}

          ⌈⌿(⍳≢⍵)(×⍤0 rank)each⍤1⊢⍵

      }


 ⍝ T3, the keyword is  ⍸ .

      subspaces←{

          frames←⍵(=⍤99 0)⍳⌈/,⍵

          rank←≢⍴⍵

          space←(⌊⌿(⊣,1∘+⍤-⍨)⌈⌿)∘↑∘⍸

          space⍤rank⊢frames

      }


 ⍝ Q2: Reshaping Reshape


 ⍝ FIXME:

 ⍝ Should the reshape function handle  ⎕IO  for robustness? This

 ⍝ is a minor issue though.

 ⍝

 ⍝ In T2 Examples,

 ⍝ "1.5 4 reshape2 ⍳10 ⍝ 1.5 truncates the data repeats the data"

 ⍝ it seems to be not cleaned up the "truncates the data".



 ⍝ Is it possible to do it by  ⍤ ?

    ∇ out←shape reshape in;idx;i

      out←in⍴⍨|shape

      idx←⍸0>,shape

      :For i :In idx

          out←⌽[i]out

      :EndFor

    ∇


 ⍝ FIXME: The T2 Example seems to be wrong!

 ⍝       ¯3 ¯2.5 phase2.reshape2 'brian' 'adam' 'morten' 'micheal'

 ⍝ ┌───────┬──────┐

 ⍝ │       │      │

 ⍝ ├───────┼──────┤

 ⍝ │micheal│morten│

 ⍝ ├───────┼──────┤

 ⍝ │adam   │brian │

 ⍝ └───────┴──────┘

 ⍝       3 2.5 phase2.reshape2 'brian' 'adam' 'morten' 'micheal'

 ⍝ ┌──────┬───────┐

 ⍝ │brian │adam   │

 ⍝ ├──────┼───────┤

 ⍝ │morten│micheal│

 ⍝ ├──────┼───────┤

 ⍝ │      │       │

 ⍝ └──────┴───────┘

      reshape2←{

          data←,⍵

          ⍝ not very clever solution

          0.5∊|⍺:data reshape⍨(×⍺)×(⌊(≢data)÷0.5~⍨|⍺)@(0.5∘=)|⍺

          1.5∊|⍺:data reshape⍨(×⍺)×(⌈(≢data)÷1.5~⍨|⍺)@(1.5∘=)|⍺

          2.5∊|⍺:((×⍺)×i@(2.5∘=)|⍺)reshape(s×i←⌈(≢data)÷s←2.5~⍨|⍺)↑data

          ⍺ reshape ⍵

      }


 ⍝ Q3: Meetings of the Minds

 ⍝ Since the sample data files are not available,

 ⍝    only a brief outline would be here.

      Attended←{

          ⍝ The idea is create a discrete representation

          ⍝ for float time intervals computed by ⎕DT

      }

 ⍝ FIXME: T2: What is the exact criteria for attending one day?

 ⍝    Marked as Attended in more than half of the sessions?

 ⍝    Or been present for more than half of the total time?

 ⍝    Or at least attended one session?

      ShowedUp←{

          ⍝ It would be just string matching by = since

          ⍝ the time and date are fixed width format.

      }

 ⍝ FIXME: T3: The "The matrix should not include any

 ⍝    sessions that are break periods" seems confusing.

 ⍝    (obscured the issue)


 ⍝ Q4: Instant-Runoff Voting

 ⍝ FIXME: T1: The box is not drawn in the last Example:

 ⍝       1 phase2.Ballot 150

 ⍝ ┌───┬─┐

 ⍝ │150│1│

 ⍝ └───┴─┘

      Ballot←{

          ⍝ candidates

          c←|⍺

          ⍺>0:{(≢⍵)⍺}⌸?⍨⍤0⊢⍵⍴c

          ⍺<0:{(≢⍵)⍺}⌸{(⍳n)@(⍵?⍨n←?⍵)⊢⍵⍴0}⍤0⊢⍵⍴c

      }


 ⍝ Slow on larger input, but works ;)

    ∇ r←IRV ballot;num;rank;vote;round;lose

      r←⍬

      num←ballot[;1]

      ⍝ if a candidate lose, the rank of

      ⍝ the ballot increase 1

      rank←1⍴⍨≢num

      vote←ballot[;2]

      lose←⍬

     loop:

      ⍝ result of each round

      round←⊃+/num×rank=vote

      r,←⊆((⍳∘≢(/⍨)×){⍺,⍵}⌸~∘0)round

      ⍝ win if has majority of *current* votes

      →((⌈/round)>2÷⍨+/num×rank∊¨vote)/win

      ⍝ tie if all identical

      →((1≥≢∘∪)round~0)/0

      ⍝ keep record of losers

      lose,←(⊢⍸⍤=(⌊/~∘0))round

      ⍝ purge losers by increase rank

      rank←{⍵+(⊃∊∘lose⍤⍸)¨⍵=vote}⍣≡rank

      →loop

     win:

      r,←⊆(⊢⍳⌈/)round

    ∇


 ⍝ Q5: Base85


 ⍝ FIXME: > 2. Convert the Step 1 result from base256 to base85

 ⍝    It would be nice to at least mention:

 ⍝    "every 32 (=4×2⍟265) bit group as an integer is decoded into 5

 ⍝    base85 numbers".

 ⍝    I referenced Wikipedia's Ascii85 page for this question.

    Original←⎕UCS 32+⍳85

      Base85←{

          ⍝ it is better off start from 0

          ⎕IO←0

          Encode←{

              data←⍵,0⍴⍨p←4|4-4|≢⍵

              ⍺[(-p)↓,⍉(5⍴85)⊤256∘⊥⍤1⊢data⍴⍨4,⍨4÷⍨≢data]

          }

          ⍝ too lazy just copy for the Encode

          Decode←{

              bin←85~⍨⍺⍳⍵

              data←bin,84⍴⍨p←5|5-5|≢bin

              (-p)↓,⍉(4⍴256)⊤85∘⊥⍤1⊢data⍴⍨5,⍨5÷⍨≢data

          }

          2|⎕DR ⍵:⍺ Encode ⍵

          ⍺ Decode ⍵

      }


 ⍝ Q6: It's a Date!

 ⍝ Really? I guess we are supposed to write parsing function

 ⍝ by hand this time. I have rarely attempted this in APL

 ⍝ so I just see how far I can get it.


 ⍝ FIXME: I have yet no idea on how to handle  "  or  '  in

 ⍝    pattern string for escaping without making the answer

 ⍝    very complex.

 ⍝    A difficult case would be handle  "  and  '  together:

 ⍝      '"''" DD '' " "'''⊃⍤(1200⌶)1232

 ⍝ ' 17  " "

 ⍝    My answer also makes assumption that only

 ⍝    character in   '_YMmDdhstP'  are treated for special,

 ⍝    and that also means "ISO week number", "day of year",

 ⍝    "Ordinal indicator" that are not shown in the Example

 ⍝    are not handled, although it should not be difficult to

 ⍝    implement them in theory by the method I use.

 ⍝

 ⍝ I suggest list all the special characters that are needed

 ⍝     to be handled to avoid any confusion.

 ⍝

 ⍝ Well, I think "compute the date given any 2~3 of year, month,

 ⍝     day, day-of-week" alone is already a complex enough

 ⍝     puzzle idea. To make this question easier some hints

 ⍝     could be provided.

 ⍝

 ⍝ The last quote and trailing space in this Example looks strange:

 ⍝     'MM/DD/YY tP:mm' DDN '02/17/22 3P:39 ''

 ⍝

 ⍝ Is a negetive number accepted result?

 ⍝       1 ⎕DT ⊂22 1 1 1 0 0 0

 ⍝ ¯685923.9583



 ⍝ It is not easy to handle the case the pattern

 ⍝ contains date like stuff for non format spec part,

 ⍝ or the variable length format spec like  'Dddd' .

 ⍝ A seemingly reliable method is compile the pattern to PCRE

 ⍝ and let  ⎕R  do all the heavy liftings, but that involves

 ⍝ escaping. I'd go with the straight forward method.


 ⍝ A good news is  'DdddDdd'  is not valid input. And I'm not

 ⍝ going to handle string escaping in this solution for the

 ⍝ reason stated in FIXME, so it is feasible to tokenize the

 ⍝ pattern by all to uppercase then compare element wise.


 ⍝ There are definitely shorter methods to generate these.

    month←'January' 'February' 'March' 'April' 'May' 'June'

    month,←'July' 'August' 'September' 'October'

    month,←'November' 'December'

    week←'Monday' 'Tuesday' 'Wednesday' 'Thursday' 'Friday'

    week,←'Saturday' 'Sunday'

      ⍝ helper functions

      ⍝ match length

    matlen←{(('|'(∊1↓∘,,⍤0)⍺)⎕S 1⍠ 'IC' 1)⍵}

      ⍝ ⍺  is a fmt spec,  ⍵  is the input,

      ⍝ return length to be take from the input

      flen←{

          'Y'=⊃⍺:≢⍺

          ⍝ length less than 3 are simple

          4>≢⍺:≢⍺

          ⍝ match month length

          'mM'∊⍨2⊃⍺:month matlen ⍵

          ⍝ match day of week length

          'dD'∊⍨2⊃⍺:week matlen ⍵

          ⍝ catch all, signal an error to debug

          ⎕SIGNAL 666

      }


 ⍝ This might be improved to handle escaping.

 ⍝ But so far it is good enough.

 ⍝       lex 'MM/DD/YY tP:mm'

 ⍝ ┌───────────────────┬─────────────────────────┐

 ⍝ │1 0 1 0 1 0 1 1 0 1│┌──┬─┬──┬─┬──┬─┬─┬─┬─┬──┐│

 ⍝ │                   ││MM│/│DD│/│YY│ │t│P│:│mm││

 ⍝ │                   │└──┴─┴──┴─┴──┴─┴─┴─┴─┴──┘│

 ⍝ └───────────────────┴─────────────────────────┘

      lex←{

      ⍝ special chars

          c←'_YMmDdhstPp'

      ⍝ format

          (⊃¨⍤⊂∘l,⍥⊂⊂∘⍵)m←(l∧1,2≠/⎕C ⍵)∨1,2≠/l←⍵∊c

      }


      label←{

          'hstP'∊⍨⊃⍵:⊃⍵

          'Y'=⊃⍵:⎕C⍣(4>≢⍵)⊢'Y' ⍝ the two digit Y

          'p'=⊃⍵:'P'

          2=≢⍵:⍵[2]

          1=≢⍵:⊃⍵

          'd'=⎕C ⍵[2]:'d'

          'm'=⎕C ⍵[2]:'M'

          ⍝ signal an error to debug

          ⎕SIGNAL 666

      }


      numval←{

          (s n)←⎕VFI ⍵

          s:n

          2≥≢⍵:'p'=⎕C⊃⍵ ⍝ AM is 0, PM is 1

          mon←∨/⍵⍷↑month

          day←∨/⍵⍷↑week

          ∨/mon:⍸mon

          ∨/day:⍸day ⍝ 1 is Monday, 7 Sunday

          ⎕SIGNAL 666

      }


    ∇ table←str parse(fmt spec);key;val;i;n

      key←⍬

      val←⍬

      :For i :In ⍳≢fmt

          :If fmt[i]

              n←(i⊃spec)flen str

              key,←label i⊃spec

              val,←numval n↑str

              str←n↓str

          :Else

              str←str↓⍨≢i⊃spec

          :EndIf

      :EndFor

    ⍝ only pick last one.

      table←key{⍺,⊃⌽⍵}⌸val

    ∇


    ⍝ Lemma: https://cs.uwaterloo.ca/~alopez-o/math-faq/node73.html

    ⍝ January 1 year N occurs on the same day of the

    ⍝ week as January 1 year N + 400.

      guessday←{

            ⍝ ⍵ is any of (mon day week) in order

            ⍝ ⍺ is a boolean mask over (mon day week)

            ⍝ year mon day week

          table←{(3↑⊃¯1 ⎕DT ⍵),3⌷⊃¯11 ⎕DT ⍵}⍤0⊢⍳146098 ⍝ 1900/1/1 to 2300/1/1

            ⍝ return (year mon day)

          (⍵≡⍤1⊢(0,⍺)/table)⌿1 1 1 0/table

      }


    ⍝ Finally

    ∇ ddn←pattern DDN string;tb;lookup;guess

      tb←string parse lex pattern

      lookup←{(tb[;2],0)[tb[;1]⍳⍵]}

      ⍝ normalize 12 hour time

      tb⍪←'h',(lookup't')+12×lookup'P'

      ⍝ Has no week of day, which is great.

      :If ~'d'∊tb[;1]

          tb⍪←3 2⍴'Y'(1900+lookup'y')'M' 1 'D' 1 ⍝ default year mon day

           ⍝ for 2 digits year num this would be negative

           ⍝ but I guess it would be fine.

          ddn←¯1 1 ⎕DT⊂lookup'YMDhms'

          :Return

      :EndIf

      ⍝ Do some guesswork

      guess←(0∘≠guessday~∘0)lookup'MDd'

      :If 'Y'∊tb[;1]

          ddn←(lookup'Y'),1↓,1↑((lookup'Y')=⍥(400∘|)guess[;1])⌿guess

      :ElseIf 'y'∊tb[;1]

          ddn←,1↑((lookup'y')=100|guess[;1])⌿guess

      :Else

          ddn←,1↑guess

      :EndIf

      ddn,←,lookup'hms'

      ddn←¯1 1 ⎕DT⊂ddn

    ∇

:EndNamespace