2
\$\begingroup\$

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.
\$\endgroup\$
0

7 Answers 7

4
\$\begingroup\$

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
\$\endgroup\$
1
  • \$\begingroup\$ The convert from binary/hexadecimal are sometimes so weird when using characters that aren't part of their conversion.. :S \$\endgroup\$ Aug 9, 2019 at 15:49
1
\$\begingroup\$

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`
\$\endgroup\$
6
  • \$\begingroup\$ *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). \$\endgroup\$
    – Grimmy
    Aug 8, 2019 at 11:09
  • 1
    \$\begingroup\$ I’ve updated the problem to reinforce the idea that an infinite loop is impossible. \$\endgroup\$
    – Ed Marty
    Aug 8, 2019 at 11:37
  • \$\begingroup\$ @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. \$\endgroup\$ Aug 8, 2019 at 11:54
  • 1
    \$\begingroup\$ 14, using 1 and 2 for white and black: *Š*‚[āIQ-W_iõq (TIO) \$\endgroup\$
    – Grimmy
    Aug 8, 2019 at 12:06
  • 1
    \$\begingroup\$ @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. ;) \$\endgroup\$ Aug 8, 2019 at 12:10
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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!

\$\endgroup\$
2
  • \$\begingroup\$ 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 \$\endgroup\$ Aug 8, 2019 at 5:45
  • \$\begingroup\$ Thank you, you found a problem. I am currently working on it. I believe you do not need bash for testing this program. \$\endgroup\$
    – user85052
    Aug 8, 2019 at 5:50
1
\$\begingroup\$

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

\$\endgroup\$
0
\$\begingroup\$

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
}
\$\endgroup\$
0
\$\begingroup\$

Python 2, 54 bytes

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

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.