You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
96 lines
2.8 KiB
96 lines
2.8 KiB
1 year ago
|
|
||
|
#naive - literal approach to the problem via a form of simulation (as attempted in https://www.youtube.com/watch?v=7fylNa2wZaU)
|
||
|
#the proper solution is of course just a little bit of maths - but the list-manipulation is an interesting exercise.
|
||
|
|
||
|
proc collapse lst {
|
||
|
#puts stdout "lst:'$lst' len:[llength $lst]"
|
||
|
foreach i $lst {
|
||
|
#puts stderr "'$i len:[llength $i] len-el0:[llength [lindex $i 0]]'"
|
||
|
if {[llength $i] == 2 && [llength [lindex $i 0]] ==2} {
|
||
|
lappend out [list [list [lindex $i 0 0] [expr {[lindex $i 0 1] + [lindex $i 1 1]}] ] ]
|
||
|
} else {
|
||
|
lappend out $i
|
||
|
}
|
||
|
}
|
||
|
return $out
|
||
|
}
|
||
|
|
||
|
#.=* list |h/0,t/tail> .=t>1*,h>end,h>end list |> punk::group_list_by {[lindex $item 0]} |> inspect |> .= collapse <q| {a 1} {b 1} {c 1}
|
||
|
|
||
|
#usage: drinkx 0 n {a 1} {b 1}...
|
||
|
pipealias drinkx .=* list {|
|
||
|
h/0,t/tail
|
||
|
>} .=t>1*,h>end,h>end list {|
|
||
|
data2,
|
||
|
nplus@end/1
|
||
|
>} {expr {$nsofar + $nplus}} {|
|
||
|
nsofar
|
||
|
>} {set data2} {|
|
||
|
|
||
|
>} punk::group_list_by {[lindex $item 0]} {|
|
||
|
|
||
|
>} .= collapse {|
|
||
|
|
||
|
>} .=>2 lmap v {lindex $v 0} {|
|
||
|
>} .=nsofar>1,n>2,data>end* list <q/2-end,nsofar/0,n/1|
|
||
|
|
||
|
|
||
|
|
||
|
input.= list {sheldon 1} {leonard 1} {penny 1} {rajesh 1} {howard 1}
|
||
|
|
||
|
|
||
|
pipealias xxx .= {list $nsofar $n {*}$q} {|
|
||
|
,
|
||
|
i/0,
|
||
|
n/1
|
||
|
>} .=>. {set in $data; while {$i < $n } {
|
||
|
#puts stdout "$i < $n"
|
||
|
#puts stdout "drinkx $in"
|
||
|
set in [drinkx {*}$in]
|
||
|
lassign $in i n
|
||
|
}; set in} {|
|
||
|
>} inspect -channel null {|
|
||
|
|
||
|
result/end
|
||
|
>} {set result} <q/2-end,nsofar/0,n/1|
|
||
|
|
||
|
|
||
|
#xxx 0 10010 {*}$input
|
||
|
#howard
|
||
|
|
||
|
#xxx 0 7230702951 {*}$input
|
||
|
#(our result is at end of list)
|
||
|
#leonard
|
||
|
|
||
|
|
||
|
set js_solution {
|
||
|
function whoIsNext(names, r){
|
||
|
let peopleInLine = names.length;
|
||
|
let copiesOfEachPerson = 1;
|
||
|
|
||
|
while (r > peopleInLine) {
|
||
|
r -= peopleInLine;
|
||
|
copiesOfEachPerson *= 2;
|
||
|
peopleInLine *= 2;
|
||
|
}
|
||
|
|
||
|
return names[Math.floor((r - 1) / copiesOfEachPerson) % peopleInLine];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
proc who_is_next {names n} {
|
||
|
set peopleInLine [llength $names]
|
||
|
set copiesOfEachPerson 1
|
||
|
while {$n > $peopleInLine} {
|
||
|
set n [expr {$n - $peopleInLine}]
|
||
|
set copiesOfEachPerson [expr {$copiesOfEachPerson * 2}]
|
||
|
set peopleInLine [expr {$peopleInLine * 2}]
|
||
|
}
|
||
|
set idx [expr {int(floor(($n -1)/$copiesOfEachPerson)) % $peopleInLine}]
|
||
|
#puts "idx:$idx names: $names"
|
||
|
set result [lindex $names $idx]
|
||
|
}
|
||
|
|
||
|
|
||
|
|