#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]
}