Black and white shirt 2 This is a more complicated version of this puzzle. The premise is the same but a few rules differ in a few key places, making for a more complex problem.

Assume I have some number of black shirts and some number of white shirts, both at least 1. Both colors of shirt have a non-zero durability. All shirts of a given color start with the same durability.

Every day, I pick out a clean shirt to wear, and it becomes dirty. Once I run out of all clean black shirts or all clean white shirts, I wash all my dirty shirts of both colors and start over. Clean shirts do not get washed. Whenever a shirt gets washed, its durability goes down by one. Immediately after washing, if the durability of a shirt reaches 0, it must be thrown out.

When picking which shirt to wear of a particular color, I specify whether I choose a shirt with highest (h) or lowest (l) remaining durability.

Challenge:

Take in an arbitrarily long sequence of four indicators (eg. bh bh bl wl bl wh wl bh...) representing my choice of shirt to wear on that day. Continue execution until either my last black shirt or my last white shirt is thrown out. Once this occurs, stop consuming input and print out the remaining shirts’ durabilities.

Inputs:

Number of black shirts, number of white shirts, durability of black shirts, durability of white shirts, and a sequence of shirt selections of arbitrary length at least long enough for one color of shirt to run out (can be considered infinitely long). The selection can be represented by a character pair (eg. bh, bl, wh, wl), or a single character (eg. b, B, w, W). Your choice, as long as there are four distinct inputs of 1 or 2 characters.

Output:

Status of each remaining shirt, sorted by durability. All shirts will be of one color.

Test cases:

The following test cases represent the amount of input the program should need to process before halting. The input is arbitrarily long otherwise.

1 1 1 1 bh
1

1 3 1 10 wh bh
10 10 9

1 5 2 10 wh wh bh wl wl wl bh
10 10 9 8 8

2 5 1 10 bh wh wh wl bl
10 10 9 9 9

1 5 6 5 wl wh bl wl wh bl wl wh bl wl wl bl wl wl wl bl wl wl wl wl bl
4 3 2 1

1 1 1 10 bl wh wh wh wh wh wh wh wh wh wh wh wh
10
#note the processing would stop occurring after the first bl and everything else should be ignored.


General rules:


This is code-golf, so shortest answer in bytes wins.
Default I/O rules apply
Perl 5, 254 bytes



sub f{@s=map[$_&gt;$_[0]||0,$_&gt;$_[0]?$_[3]:$_[2],1],1..$_[0]+$_[1];while(join('',map$$_[0],@s)=~/01|10/){($c,$p)=&amp;{$_[4]};(@w=sort{$p*($$b[1]&lt;=&gt;$$a[1])}grep$$_[2]&amp;&amp;$$_[0]eq$c,@s)[0][2]=0;@s=grep$$_[2]||++$$_[2]&amp;&amp;--$$_[1],@s if@w&lt;2}sort{$b&lt;=&gt;$a}map$$_[1],@s}


Try it online!

Ungolfed but same – with tests:

use Test::More tests=&gt;6;
sub fu {
  my($countb,$countw,$durb,$durw,$get_todays)=@_;            #get 5 inputs
  my @s=( (map{{col=&gt;'b',dur=&gt;$durb,clean=&gt;1}}1..$countb),   #init shirts array
          (map{{col=&gt;'w',dur=&gt;$durw,clean=&gt;1}}1..$countw) );
  while(join('',map$$_{col},@s)=~/bw|wb/){                   #while still both colors left
    my($col,$p) = &amp;$get_todays;                              #todays color and preference
    my @w = grep $$_{clean} &amp;&amp; $$_{col} eq $col, @s;         #@w=wearable shirts
    my $shirt = (sort{$p*($$b{dur}&lt;=&gt;$$a{dur})}@w)[0];       #pick todays shirt w/most|least durability left 
    $$shirt{clean}=0;                                        #dirty in the evening
    map{$$_{clean}=1;$$_{dur}--}grep!$$_{clean},@s if @w==1; #wash if there was only one this morning
    @s=grep$$_{dur}&gt;0,@s;                                    #toss out worn outs
  }
  return sort{$b&lt;=&gt;$a}map$$_{dur},@s
}
my @test=(
'1 1 1 1 bh',                                                             '1',
'1 3 1 10 wh bh',                                                         '10 10 9',
'1 5 2 10 wh wh bh wl wl wl bh',                                          '10 10 9 8 8',
'2 5 1 10 bh wh wh wl bl',                                                '10 10 9 9 9',
'1 5 6 5 wl wh bl wl wh bl wl wh bl wl wl bl wl wl wl bl wl wl wl wl bl', '4 3 2 1',
'1 1 1 10 bl wh wh wh wh wh wh wh wh wh wh wh wh',                        '10'  #should see sequence not empty
);
while(@test){
  my($countb,$countw,$durb,$durw,@col)=split' ',shift@test;
  my @expected                        =split' ',shift@test;
  my $msg='';
  my $feederu=sub{ (shift(@col)//do{@expected='!',$msg='sequence ran out!'})
                   =~/(.)(.)/;($1,{h=&gt;1,l=&gt;-1}-&gt;{$2}) };
  my $feeder=sub{ (shift(@col)//do{@expected='!',$msg='sequence ran out!'})
                   =~/(.)(.)/;($1 eq 'w'||0,{h=&gt;1,l=&gt;-1}-&gt;{$2}) };
  my @got=fu($countb,$countw,$durb,$durw,$feederu);
 #my @got=f($countb,$countw,$durb,$durw,$feeder);
  $msg='sequense not empty' if @col;
  is(join(" ",@got),
     join(" ",@expected), $msg);
}