Home » Last Selected Queue Item

Last Selected Queue Item

For production runs, number of items (say N) to be selected in one go is given in every column. First it selects N items from the front and then N items from the back and then N from the front, then N from back and keeps repeating. Find the last item to be selected. Ex. Queue has A, B, C, D, E, F and N = 2. First A & B will be selected, then E & F will be selected and finally C & D will be selected. Hence, last item to be selected is D.

📌 Challenge Details and Links
ExcelBI Excel Challenge Number: 679
Challenge Difficulty: ⭐️⭐️
📥Download Sample File
📥Link to the solutions on LinkedIn

Solving the challenge of Last Selected Queue Item with Power Query

Power Query solution 1 for Last Selected Queue Item, proposed by Kris Jaganah:
let
  A = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  B = Table.ToColumns(A), 
  C = List.Transform(
    B, 
    each [
      a = Text.Combine(List.Skip(_)), 
      b = Text.Length(a), 
      c = List.Max({_{0}, List.Median({1 .. b})}), 
      d = if Number.IsOdd(b) then c else Number.IntegerDivide(c, 1) + _{0}, 
      e = Text.At(a, d - 1)
    ][e]
  ), 
  D = Table.FromColumns({Table.ColumnNames(A), C}, {"Run", "Last Item"})
in
  D
Power Query solution 2 for Last Selected Queue Item, proposed by Luan Rodrigues:
let
  Fonte = List.Transform(
    Table.ToColumns(Tabela1), 
    (x) =>
      [
        a = List.RemoveNulls(x), 
        b = a{0}, 
        c = List.Split(List.Skip(a), b), 
        d = List.Combine(List.Transform(c, (y) => List.Reverse(y))), 
        e = List.Median({1 .. List.Count(d)}), 
        f = 
          if List.Count(d) = b then
            List.First(d)
          else if e = Number.RoundDown(e, 0) then
            d{Number.RoundUp(e)}
          else
            d{Number.RoundUp(e) - 1}
      ][f]
  ), 
  res = Table.FromRows(List.Zip({Table.ColumnNames(Tabela1), Fonte}), {"Run", "Last Item"})
in
  res
Power Query solution 3 for Last Selected Queue Item, proposed by Ramiro Ayala Chávez:
let
  S = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  a = Table.ToColumns(S), 
  b = List.Transform(a, List.RemoveNulls), 
  Fx = (x) =>
    let
      c = List.Split(List.Skip(x), x{0}), 
      d = Number.RoundDown(List.Count(c) / 2), 
      e = if Number.IsOdd(d) then List.First(c{d}) else List.Last(c{d})
    in
      e, 
  f = List.Transform(b, each Fx(_)), 
  Sol = Table.FromRows(List.Zip({Table.ColumnNames(S), f}), {"Run", "Last Item"})
in
  Sol
Power Query solution 4 for Last Selected Queue Item, proposed by Seokho MOON:
let
  Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  Res = Table.FromList(Table.ToColumns(Table.DemoteHeaders(Source)), Fun_1, {"Run", "Last Item"}), 
  Fun_1 = each {_{0}, List.Last(List.Last(Fun_2(List.Skip(_, 2), {}, _{1})))}, 
  Fun_2 = (x as list, y as list, n as number) =>
    [
      A = {{List.RemoveFirstN, List.FirstN}, {List.RemoveLastN, List.LastN}}, 
      B = {List.RemoveNulls(x), Number.Mod(List.Count(y), 2)}, 
      C = if B{0} = {} then y else @Fun_2(A{B{1}}{0}(B{0}, n), y & {A{B{1}}{1}(B{0}, n)}, n)
    ][C]
in
  Res
Power Query solution 5 for Last Selected Queue Item, proposed by Peter Krkos:
let
  F = (lst as list, n) =>
    [
      a   = lst, 
      num = Number.From(n), 
      b   = List.RemoveFirstN(a, num), 
      c   = if List.Count(b) > num then List.RemoveLastN(b, num) else b
    ][c], 
  Gen = List.TransformMany(
    Table.ToColumns(Source), 
    each {List.Skip(List.RemoveNulls(_))}, 
    (x, y) =>
      List.Last(
        List.Last(
          List.Generate(
            () => if List.Count(y) <= Number.From(x{0}) then y else F(y, x{0}), 
            each List.Count(_) > 0, 
            each F(_, x{0})
          )
        )
      )
  ), 
  Tbl = Table.FromRows(
    List.Zip({Table.ColumnNames(Source), Gen}), 
    type table [Run = text, Last Item = text]
  )
in
  Tbl
Power Query solution 6 for Last Selected Queue Item, proposed by Alexandre Garcia:
let
  A = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content], 
  B = List.Transform(
    Table.ToColumns(A), 
    (v) =>
      List.Last(
        List.Last(
          List.Generate(
            () => List.Skip(List.RemoveNulls(v)), 
            each _ <> {}, 
            each List.RemoveLastN(List.Skip(_, v{0}), v{0})
          )
        )
      )
  ), 
  C = Table.FromRows(List.Zip({Table.ColumnNames(A), B}), {"Run", "Last Item"})
in
  C

Solving the challenge of Last Selected Queue Item with Excel

Excel solution 1 for Last Selected Queue Item, proposed by Bo Rydobon 🇹🇭:
=TRANSPOSE(VSTACK(A2:D2,BYCOL(A3:D19,LAMBDA(x,INDEX(x,COUNTA(x)-FLOOR(COUNTA(x)-2,@+x*2)/2)))))

=TRANSPOSE(VSTACK(A2:D2,BYCOL(A3:D19,LAMBDA(x,LET(s,INT(SEQUENCE(COUNTA(x)-1,,0)/@+x),INDEX(x,1+XMATCH(0,s+SORT(-s),1,-1)))))))
Excel solution 2 for Last Selected Queue Item, proposed by John V.:
=TRANSPOSE(VSTACK(A2:D2,BYCOL(A3:D19,LAMBDA(r,LET(s,SEQUENCE,z,COUNTA(r)-1,i,-INT(-z/@+r)-1,INDEX(r,1+MAX(IF(i,REDUCE(s(z),s(i)-1,LAMBDA(a,v,DROP(a,@+r*-1^v))),s(z)))))))))
Excel solution 3 for Last Selected Queue Item, proposed by 🇰🇷 Taeyong Shin:
=LET(
    R,
    LAMBDA(
        R,
        x,
        i,
        IF(
            ROWS(
                x
            )>i*2,
            R(
                R,
                DROP(
                    DROP(
                        x,
                        i
                    ),
                    -i
                ),
                i
            ),
            LOOKUP(
                "z",
                x
            )
        )
    ),
    TRANSPOSE(
        VSTACK(
            A2:D2,
            BYCOL(
                A3:D19,
                LAMBDA(
                    c,
                    R(
                        R,
                        DROP(
                            TOCOL(
                                c,
                                1
                            ),
                            1
                        ),
                        N(
                            c
                        )
                    )
                )
            )
        )
    )
)
Excel solution 4 for Last Selected Queue Item, proposed by Kris Jaganah:
=WRAPCOLS(HSTACK(A2:D2,BYCOL(A3:D19,LAMBDA(x,LET(a,CONCAT(x),b,--LEFT(a),c,LEN(a)-1,e,SEQUENCE(c),f,MAX(b,MEDIAN(e)),g,IF(ISODD(c),f,INT(f)+b),MID(a,g+1,1))))),4)
Excel solution 5 for Last Selected Queue Item, proposed by Julian Poeltl:
=LET(A,A2:D19,S,SEQUENCE(COLUMNS(A)),VSTACK(HSTACK("Run","Last Item"),HSTACK("Run"&S,CHAR(64+MAP(S,LAMBDA(B,LET(M,INDEX(A,2,B),R,COUNTA(INDEX(A,,B))-2,RD,ROUNDDOWN(R/M,),TAKE(UNIQUE(TOCOL(TOCOL(HSTACK(SEQUENCE(RD,,,M),SEQUENCE(RD,,R-M+1,-M)))+SEQUENCE(,M,0))),-1))))))))
Excel solution 6 for Last Selected Queue Item, proposed by Timothée BLIOT:
=HSTACK(TOCOL(A2:D2),MAP(SEQUENCE(4),LAMBDA(x,LET(A,INDEX(A4:D19,,x),B,FILTER(A,A<>0),C,INDEX(A3:D3,,x),TAKE(REDUCE(B,SEQUENCE(CEILING(ROWS(B)/C,1)+1),LAMBDA(w,v,IF((v<3),w,IF(ISODD(v),DROP(w,C),DROP(w,-C))))),-1)))))
Excel solution 7 for Last Selected Queue Item, proposed by Hussein SATOUR:
=TRANSPOSE(BYCOL(A3:D19,LAMBDA(z,LET(r,z,n,TAKE(r,1),a,DROP(r,1),w,CONCAT(a),b,SCAN(w,SEQUENCE(COUNTA(a))^0,LAMBDA(x,y,MID(x,y+n,LEN(x)-2*n))),RIGHT(IFERROR(TAKE(TOCOL(IF(b="",1/0,b),3),-1),w))))))
Excel solution 8 for Last Selected Queue Item, proposed by LEONARD OCHEA 🇷🇴:
=LET(i,A4:D19,C,TOCOL,l,BYCOL(i,COUNTA),k,A3:D3,HSTACK(C(A2:D2),C(INDEX(i,l-k*INT((l-k)/2/k)-k*MOD(l,k),k))))

=LET(C,TOCOL,t,BYCOL(A4:D19,LAMBDA(x,CONCAT(TOROW(x)))),l,LEN(t),k,A3:D3,HSTACK(C(A2:D2),C(MID(t,l-k*INT((l-k)/2/k)-k*MOD(l,k),1))))
Excel solution 9 for Last Selected Queue Item, proposed by Pieter de B.:
=TRANSPOSE(VSTACK(A2:D2,BYCOL(A2:D21,LAMBDA(a,LET(c,CONCAT(DROP(a,2)),n,@+DROP(a,1),REDUCE(c,SEQUENCE(INT(LEN(c)/n)),LAMBDA(x,y,LET(r,RIGHT,z,IF(ISODD(y),LEFT,r),IF(LEN(x)<=n,r(x),SUBSTITUTE(x,z(x,n),))))))))))
Or
=REDUCE({"Run","Last Item"},A2:D2,LAMBDA(a,b,LET(c,DROP(TAKE(b:D21,,1),1),d,@+c,VSTACK(a,HSTACK(b,REDUCE(TOCOL(DROP(c,1),1),SEQUENCE(ROWS(c)/d),LAMBDA(x,y,IF(ROWS(x)<=d,TAKE(x,-1),DROP(x,d*IF(ISODD(y),1,-1))))))))))
Excel solution 10 for Last Selected Queue Item, proposed by Jaroslaw Kujawa:
=TRANSPOSE(
    VSTACK(
        A2:D2;
        BYCOL(
            A3:D19;
            LAMBDA(
                x;
                LET(
                    n;
                    COUNTA(
                        x
                    )-1;
                    CHOOSEROWS(
                        x;
                        1+IF(
                            TAKE(
                                x;
                                1
                            )<>n;
                            TAKE(
                                x;
                                1
                            )+n/2;
                            TAKE(
                                x;
                                1
                            )
                        )
                    )
                )
            )
        )
    )
)
Excel solution 11 for Last Selected Queue Item, proposed by JvdV -:
=TRANSPOSE(
    VSTACK(
        A2:D2,
        BYCOL(
            A3:D19,
            LAMBDA(
                c,
                LET(
                    n,
                    @+c,
                    d,
                    DROP,
                    x,
                    LAMBDA(
                        f,
                        s,
                        IF(
                            ROWS(
                                s
                            )>2*n,
                            f(
                                f,
                                d(
                                    d(
                                        s,
                                        n
                                    ),
                                    -n
                                )
                            ),
                            TAKE(
                                s,
                                -1
                            )
                        )
                    ),
                    x(
                        x,
                        d(
                            TOCOL(
                                c,
                                1
                            ),
                            1
                        )
                    )
                )
            )
        )
    )
)
Excel solution 12 for Last Selected Queue Item, proposed by Sandeep Marwal:
=LET(
    
    range,
    A4:A11,
    
    countofchar,
    COUNTA(
        range
    ),
    
    run,
    A3,
    
    remainder,
    MOD(
        countofchar,
        run
    ),
    
    subt,
    IF(
        remainder=0,
        countofchar-run,
        countofchar-remainder
    ),
    
    dp_1,
    ROUNDUP(
        subt/2/run,
        0
    )*run,
    
    dp_2,
    ROUNDDOWN(
        subt/2/run,
        0
    )*run,
    
    st_1,
    DROP(
        range,
        dp_1
    ),
    
    st_2,
    DROP(
        st_1,
        -dp_2
    ),
    
    result,
    TAKE(
        st_2,
        -1
    ),
    
    result
    
)
Excel solution 13 for Last Selected Queue Item, proposed by Ben Warshaw:
=LET(
    
     _Run_1,
     A3:D3,
    
     _Run_2,
     A4:D19,
    
     _Step1,
     BYCOL(
         _Run_2,
          COUNTA
     ),
    
     _Step2,
     _Step1 / _Run_1,
    
     _Step3,
     BYCOL(
         
          _Step1,
         
          LAMBDA(
              x,
               IF(
                   ISODD(
                       x
                   ),
                    ROUND(
                        x / 2,
                         0
                    ),
                    ROUND(
                        x / 2,
                         0
                    ) + 1
               )
          )
          
     ),
    
     _Step4,
     CEILING(
         _Step3,
          _Run_1
     ) - IF(
         INT(
             _Step2
         ) <> _Step2,
          1,
          0
     ),
    
     _Result,
     TOCOL(
         INDEX(
             _Run_2,
              _Step4,
              _Run_1
         )
     ),
    
     _Result
    
)

Solving the challenge of Last Selected Queue Item with Python

Python solution 1 for Last Selected Queue Item, proposed by Konrad Gryczan, PhD:
import pandas as pd
path = "679 Last Item to be Selected.xlsx"
input = pd.read_excel(path, usecols="A:D", skiprows=1, nrows=18)
test = pd.read_excel(path,  usecols="F:G", skiprows=1, nrows=4)
df = input.fillna('')
def last_item(data):
 N = int(data[0])
 items = [i for i in data[1:] if i]
 front = True
 while len(items) > N:
 if front:
 items = items[N:]
 else:
 items = items[:-N]
 front = not front
 return items[-1]
result = pd.DataFrame({
 'Run': df.columns,
 'Last Item': [last_item(df[column].tolist()) for column in df.columns]
})
print(result.equals(test)) # True
                    
                  

Solving the challenge of Last Selected Queue Item with Python in Excel

Python in Excel solution 1 for Last Selected Queue Item, proposed by Alejandro Campos:
df = xl("A2:D19", headers=True).fillna('')
def last_item(data):
 N, items, front = int(data[0]), [i for i in data[1:] if i], True
 while len(items) > N: items, front = (items[N:], not front) if front else (items[:-N], not front)
 return items[-1]
pd.DataFrame({'Run': df.columns, 'Last Item': [last_item(df[c].tolist()) for c in df.columns]})
                    
                  
Python in Excel solution 2 for Last Selected Queue Item, proposed by &Aditya Kumar Darak 🇮🇳:
import math
df = xl("A2:D19", True)
N = df.iloc[0].astype(int)
Lsts = df.iloc[1:].apply(lambda col: col.dropna().tolist(), axis=0)
def MyFun(lst, n):
 L = len(lst)
 k = math.ceil(L / n)
 d = "F" if k % 2 == 1 else "B"
 r = L - (k - 1) * n
 if d == "F":
 return lst[(k // 2) * n + r - 1]
 else:
 return lst[L - 1 - ((k - 1) // 2) * n]
Last = Lsts.index.to_series().apply(lambda run: MyFun(Lsts[run], N[run]))
result = pd.DataFrame({"Run": Last.index, "Last": Last.values})
result
                    
                  

Solving the challenge of Last Selected Queue Item with R

R solution 1 for Last Selected Queue Item, proposed by Konrad Gryczan, PhD:
library(tidyverse)
library(readxl)
path = "Excel/679 Last Item to be Selected.xlsx"
input = read_excel(path, range = "A2:D19")
test  = read_excel(path, range = "F2:G6")
 
last_item = function(data) {
 N = as.numeric(data[1])
 items = na.omit(data[-1])
 front = TRUE
 while (length(items) > N) {
 items = if (front) items[(N + 1):length(items)] else items[1:(length(items) - N)]
 front =  !front
 }
 items[length(items)]
}
result = data.frame(
 Run = names(input),
 items = map_chr(input, last_item)
)
all.equal(result, test, check.attributes = FALSE)
#> [1] TRUE
                    
                  

&&

Leave a Reply