Black and white shirts

1

0

This puzzle is based on this Math.SE post. A more complex version of this problem can be found over here.

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 always choose a shirt with the highest durability of that color to ensure even wear and tear among shirts.

Challenge:

Take in a sequence of two characters of infinite length (eg. b b b w b w w b...) 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 halt execution immediately. Note that the program must not consume any more input than is required before halting.

Inputs:

Number of black shirts, number of white shirts, durability of black shirts, durability of white shirts, and an infinite number of two single characters, your choice (eg. b and w)

Note: if your language of choice does not support reading input of an infinite length (i.e. from a stream), assume an input of arbitrary length that is at least long enough for one color of shirt to run out.

Output:

None. The program must simply immediately halt when the last shirt of either color is thrown away.

Note: if your language does not support reading input of infinite length, then instead you should output the number of characters processed.

Test cases:

The following test cases represent the amount of input the program should process before halting. The sequence of w’s and b’s is infinite. The parenthetical afterwards is not part of the input or output, but simply represents the end state of how many shirts of each color have not been thrown out.

1 1 1 1 b
(0 b, 1 w left)

1 999 1 999 b
(0 b, 999 w left)

1 999 1 999 w w w w w w w w b
(0 b, 999 w left)

2 999 1 999 b w w w b
(0 b, 999 w left)

2 999 2 999 b w w w b w b w w w b
(0 b, 999 w left)

5 6 3 1 w w w w w b b b b b b b b b b b b b b w
(5 b, 0 w left)

General rules:

  • This is , so shortest answer in bytes wins.
  • Default input rules apply for the first four arguments. For the arbitrarily long input sequence after the first four arguments, input must come from a source which can provide input one character or byte at a time, of theoretically infinite length, such as STDIN or some other stream. If your language of choice does not support these features, see above.

Ed Marty

Posted 2019-08-08T04:51:55.563

Reputation: 265

Answers

4

05AB1E, 14 bytes

*Š*‚[ICÓ-W_iõq

Try it online!

Uses p instead of b, because pink is prettier than black.

Explanation:

*             # number of white shirts * durability of white shirts
 Š            # swap
  *           # number of pink shirts * durability of pink shirts
   ‚          # pair the two products in a list
[             # infinite loop
 I            # get the next input
  =           # print (only in the TIO version, not actually needed)
   C          # convert from binary (this yields 51 for p and 58 for w, don't ask why)
    Ó         # list of exponents in the prime factorization
     -        # subtract from the durability list
      W_i     # if the minimum of the list is now 0
         õq   # exit without printing anything

Grimmy

Posted 2019-08-08T04:51:55.563

Reputation: 12 521

The convert from binary/hexadecimal are sometimes so weird when using characters that aren't part of their conversion.. :S – Kevin Cruijssen – 2019-08-09T15:49:32.180

1

C(tcc), 117 116 90 bytes

Uses 0x01 instead of b, and 0x02 instead of w.

main(a,b,c,d){scanf("%d%d%d%d",&a,&b,&c,&d);a*=c;for(b*=d;a*b;~c?b-=!c:a--)c=getchar()-2;}

Try it online!

user85052

Posted 2019-08-08T04:51:55.563

Reputation:

How can I tell it's working from the link? I think you'd need to use some bash for that, but I have no clue how – Unrelated String – 2019-08-08T05:45:26.620

Thank you, you found a problem. I am currently working on it. I believe you do not need bash for testing this program. – None – 2019-08-08T05:50:51.053

1

05AB1E, 28 22 bytes

*U*V[XY*_iõq}©XαUY®≠-V

Inputs are separated by newlines in the order amountOfWhiteShirts, whiteDurability, amountOfBlackShirts, blackDurability, shirtDigits..., where white shirts are 1 and black shirts are 0.

-3 bytes thanks to @Grimy by bringing to my attention that an input of 1/0 instead of "w"/"b" is allowed for the shirts.

Try it online or try it online with additional = to print shirts without popping to verify it works as intended.

Explanation:

*          # Multiply the first two (implicit) input-integers
 U         # Pop and store it in variable `X`
*          # Multiply the next two (implicit) input-integers
 V         # Pop and store it in variable `Y`
[          # Start an infinite loop:
 XY*_i  }  #  If either `X` or `Y` is 0:
      õ    #   Push an empty string, since we don't want any (implicit) output
       q   #   And stop the program
 ©         #  Store the next (implicit) input in variable `®` (without popping)
  Xα       #  Get it's absolute difference with `X` (basically `X-input`)
    U      #  Pop and store it as new value for `X`
  ®≠       #  Push `®` falsified (1→0; 0→1)
 Y  -      #  Then subtract it from `Y`: `Y-falsified(®)`
     V     #  And also pop and store it as new value for `Y`

Kevin Cruijssen

Posted 2019-08-08T04:51:55.563

Reputation: 67 575

*U*X‚ could be *Š*‚. The challenge allows using arbitrary characters instead of b and w, so 'wQ could be entirely removed (just choose 1 for white and 0 for black). – Grimmy – 2019-08-08T11:09:10.163

1I’ve updated the problem to reinforce the idea that an infinite loop is impossible. – Ed Marty – 2019-08-08T11:37:54.983

@Grimy I've removed the second program now that the specs have been improved. Thanks for bringing to my attention that 1/0 is allowed for this shirts, though. – Kevin Cruijssen – 2019-08-08T11:54:45.447

@EdMarty Ok, now it makes a bit more sense. :) I've changed my answer accordingly. – Kevin Cruijssen – 2019-08-08T11:55:26.103

1

14, using 1 and 2 for white and black: *Š*‚[āIQ-W_iõq (TIO)

– Grimmy – 2019-08-08T12:06:36.730

1@Grimy Oh, very nice approach! Love the ā. It looks nothing like my answer though. Maybe it's better if you post it yourself? Apart from the iõq I see nothing of my answer in yours. ;) – Kevin Cruijssen – 2019-08-08T12:10:36.863

1

Charcoal, 22 bytes

F²⊞υ×NNW∧⌊υS§≔υ℅ι⊖§υ℅ι

Try it online! Link is to verbose version of code. Requires both black shirt values, then both white shirt values, then a stream of b and w characters on separate lines, otherwise behaviour is undefined. On TIO if you don't provide enough shirts you can see Charcoal attempt to prompt for input; if you ran locally then you would be able to continue enter b and w characters until you ran out of shirts at which point the program would exit. Explanation:

F²⊞υ×NN

Calculate the lifetimes of each colour of shirt.

W∧⌊υS

Repeat until one colour is exhausted.

§≔υ℅ι⊖§υ℅ι

Reduce the lifetime of a shirt according to the worn colour.

Neil

Posted 2019-08-08T04:51:55.563

Reputation: 95 035

1

C# .NET, 260 bytes

class P{static void Main(string[]a){int b=int.Parse(a[0]);int g=int.Parse(a[1]);int q=g;int r=int.Parse(a[2]);int t=int.Parse(a[3]);int w=t;while(true){if(System.Console.ReadKey().KeyChar<104)q--;else w--;if(q<1){q=g;b--;}if(w<1){w=t;r--;}if(r<1|b<1)return;}}}

No TIO :(
Not the shortest but does the job great!
EDIT: NOTE: uses no spaces in input and (g)reen and (r)ed instead of (b)lack and (w)hite

canttalkjustcode

Posted 2019-08-08T04:51:55.563

Reputation: 131

0

Perl 5, 205 bytes

sub f{@s=map[$_>$_[0]?'w':'b',$_>$_[0]?$_[3]:$_[2],1],1..$_[0]+$_[1];while(join('',map$$_[0],@s)=~/bw|wb/){$c=&{$_[4]};(@w=grep$$_[2]&&$$_[0]eq$c,@s)[0][2]=0;@s=grep$$_[2]||++$$_[2]&&--$$_[1],@s if@w<2}@s}

Try it online!

I assumed that picking the least worn out shirt each day doesn't actually influence the result. Any clean shirt of the chosen color will do. I also think that 2 shirts of durability 5 is the same as 1 shirt of durability 10, so we can simplify this to have just two shirts, one black and one white, but that affects the printed (x b, y w left) result so I didn't go that direction.

Ungolfed:

sub f0 {                                                     #as f() but ungolfed
  my($countb,$countw,$durb,$durw,$get_todays_color)=@_;      #inputs
  my @s=( (map{{col=>'b',dur=>$durb,clean=>1}}1..$countb),   #init @shirts
          (map{{col=>'w',dur=>$durw,clean=>1}}1..$countw) );
  while(join("",sort(map$$_{col},@s))=~/bw/){                #while still both colors available                                                                                                                      
    my $col = &$get_todays_color;                            #todays color                                                                                                                                      
    my @w = grep $$_{clean} && $$_{col} eq $col, @s;         #wearable shirts                                                                                                                                   
    my $s = (sort{$$b{dur}<=>$$a{dur}}@w)[0];                #pick shirt with most durability left for today                                                                                                    
    $$s{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}>0,@s;                                    #toss out worn outs                                                                                                                                
  }
  @s                                                         #return not worn out
}

Kjetil S.

Posted 2019-08-08T04:51:55.563

Reputation: 1 049

0

Python 2, 54 bytes

b,w,B,W=input()
l=[B*b,W*w]
while all(l):l[input()]-=1

Try it online!

Erik the Outgolfer

Posted 2019-08-08T04:51:55.563

Reputation: 38 134