Grocery Store Micromanagement

14

3

You are an employee at the hip new grocery store Half Foods, and it's the day before Thanksgiving Christmas Easter. Since the store will be packed with customers rushing to get their foodstuffs, the store needs a traffic manager to send everyone to the appropriate lines. Being lazy, you'd like to automate this so that you can go hit the deli before everyone takes all the turkey ham whatever. However, all you have with you is your phone, and coding long programs on it is a real pain -- so you need to bust out your ninja skills.

Challenge

Let's visualize the grocery store on a two-dimensional grid. Here's a sample grid to dissect:

                             e
                             s
                             s
                             s
                               Y

#           #                #s           #
#s          #                #s           #
#s          #                #s           #
#s          #s               #s           #
#3          #1               #4           #
 x           x                x            x

The grid starts out with an e, which represents an "outlet" to the rest of the store. Every generation, all of the outlets in the grid spawn a shopper (s) directly below. The shoppers move downward each generation until they reach you (Y). When a shopper reaches the same row as you, you must teleport the shopper to the beginning of the line with the least amount of shoppers in it. A shopper immediately moves to the line when they would move into the row with the Y, there is no generation in between. The lines are represented by the #s -- the column after the #s is a line. The shoppers go down to the end of the line (represented by an exit x), and then turn into a random number between 1 and 5. Each generation, you must decrement numbered shoppers by 1 -- when a shopper would reach 0, they're done checking out and they leave the store.

Given an input of a grid like this, output the next generation of the grocery store (move all the shoppers down simultaneously, redirect shoppers, and have them leave if they are done).

Samples

Input:

                e

                     Y


#           #                #            #
#           #                #            #
#           #                #            #
#           #                #            #
#           #                #            #
 x           x                x            x

Output:

                e
                s 
                     Y


#           #                #            #
#           #                #            #
#           #                #            #
#           #                #            #
#           #                #            #
 x           x                x            x

Input:

                e
                s 
                     Y


#           #                #            #
#           #                #            #
#           #                #            #
#           #                #            #
#           #                #            #
 x           x                x            x

Output

                e
                s 
                     Y


#s          #                #            #
#           #                #            #
#           #                #            #
#           #                #            #
#           #                #            #
 x           x                x            x

Input:

                e

                     Y


#           #                #            #
#           #                #            #
#           #                #            #
#s          #                #            #
#           #                #            #
 x           x                x            x

(Possible) Output:

                e
                s 
                     Y


#           #                #            #
#           #                #            #
#           #                #            #
#           #                #            #
#3          #                #            #
 x           x                x            x

Input:

                e
                s 
                     Y


#           #                #            #
#           #                #            #
#           #                #            #
#           #                #            #
#3          #                #            #
 x           x                x            x

Output:

                e
                s 
                     Y


#           #s               #            #
#           #                #            #
#           #                #            #
#           #                #            #
#2          #                #            #
 x           x                x            x

Input:

                e

                     Y


#           #                #            #
#           #                #            #
#           #                #            #
#           #                #            #
#1          #                #            #
 x           x                x            x

Output:

                e
                s 
                     Y


#           #                #            #
#           #                #            #
#           #                #            #
#           #                #            #
#           #                #            #
 x           x                x            x

This is , so shortest code wins.

a spaghetto

Posted 2016-02-14T21:43:38.123

Reputation: 10 647

1I really don't get the input format. – Fund Monica's Lawsuit – 2016-04-22T23:39:35.943

@QPaysTaxes Input can be either a multi-line string or an array of single line strings as per our defaults for taking multiple lines of input. – a spaghetto – 2016-04-22T23:40:50.467

No, I mean that I just don't get the challenge, really. – Fund Monica's Lawsuit – 2016-04-22T23:41:33.330

Rather than rely on the examples, it might be worth stating explicitly that the shopper can never be on the same row as Y, as moving down to the Y row and being teleported to the top of the relevant queue happen in a single step. – trichoplax – 2016-04-23T00:09:16.703

It would also help to have a description of how a queue moves, with a test case as an example. If there are 3 shoppers vertically adjacent in a queue, and the lowest can move down, do all 3 move down together in a single step or does the available space move up one row at a time as each shopper moves into it? – trichoplax – 2016-04-23T00:11:46.997

This sounds fun. Will the lines (#s) always be the same length as each other? Should shoppers always be sent to the queue with the least people? E.g. 5sss is likely slower than 1ssss, by 1 generation on average. Or is the point to simulate the uncertainty of this situation in real life? :) – Chris M – 2017-01-07T14:59:31.690

@ChrisM Very belated but yes they'll be the same length. I didn't want to overcomplicate the line selection procedure even though there's a chance shorter lines could be slower. – a spaghetto – 2017-04-24T21:59:27.520

Do we assume that there will always be 4 lines of #, and, if yes, do we assume that the array are always at the same position ? Also, do we assume that the input will the result of a previous generation ? – HatsuPointerKun – 2017-07-23T22:50:51.637

@HatsuPointerKun There can be an arbitrary number of lines. I can add examples with more lines if necessary. – a spaghetto – 2017-07-24T02:53:14.713

Answers

4

Python 2, 477 463 453 449 423 402 397 396 393 bytes

t=input()
e=enumerate
q,r=" s"
for i,L in list(e(t))[:0:-1]:
 for j,c in e(L):
	a=t[i-1][j]
	if"0"<c<"6":L[j]="0 1234"[int(c)]
	if(r==a)*q==L[j]:t[i-1][j],L[j]=q+r
	if"e"==a:L[j]=r
	if r==L[j]and"x"==t[i+1][j]:L[j]="5"
 if"Y"in L:x=L.count(r);t[i]=[p.replace(r,q)for p in L]
for i,l in list(e(t))[::-1]:
 for j,c in e(l):
	if"#"==c and(q==l[j+1])*x:x-=1;l[j+1]=r
print"\n".join(map("".join,t))

Try it online!

Still working on golfing this but it solves the problem for now

Post Rock Garf Hunter

Posted 2016-02-14T21:43:38.123

Reputation: 55 382

You can remove excess indentation and line breaks (single line blocks can go on the same line as the start of the block) – Solomon Ucko – 2017-07-23T15:02:45.400

@SolomonUcko Where are you talking about? – Post Rock Garf Hunter – 2017-07-23T15:06:10.210

>

  • Are tabs 8 spaces to python? 2. I think you can remove the line breaks after the last 2 for loops.
  • < – Solomon Ucko – 2017-07-23T19:38:25.897

    1>

  • Tabs are their own thing in Python. 2. You can't remove that line break.
  • < – Post Rock Garf Hunter – 2017-07-23T19:42:09.167

    >

  • Does python just count the first indentation level in a block as the indentation level for that block? 2. Do you know why not? I tested it and it doesn't work.
  • < – Solomon Ucko – 2017-07-23T20:07:38.593

    BTW, wow about the program. – Solomon Ucko – 2017-07-23T20:09:59.880

    I've updated to spec to clarify this, but the "when a shopper reaches 0 they leave" means that when a shopper would reach 0 they leave, not the generation after they hit 0. (That is if you have a shopper at 1 they will be gone next generation). The last example illustrates this. – a spaghetto – 2017-07-24T02:52:02.950

    Other than that this seems great. I originally hadn't considered multiple entrances but since your program supports it I'll update the spec to specify there can be multiple. – a spaghetto – 2017-07-24T02:58:57.243

    @quartata Cool I fixed the problem. Unfortunately it didn't save any bytes to remove zero. But on the bright side it didn't cost any either. – Post Rock Garf Hunter – 2017-07-24T03:20:00.683

    how did you get a bounty from the community? – FantaC – 2017-12-23T20:58:24.397

    @tfbninja There was a bounty that expired and I had the top voted new answer so I received half of it. – Post Rock Garf Hunter – 2017-12-23T22:00:38.147

    4

    C++, 898 896 885 841 bytes

    Very long to code... but it's there

    -2 bytes thanks to Conor O'Brien
    -45 byte thanks to Zacharý

    #include<vector>
    #include<string>
    #include<algorithm>
    #include<ctime>
    #define B begin()
    #define L length()
    #define C(e)if(i[j].find(e)!=string::npos&&!
    #define S's'
    #define T size()
    #define U i[x][a]
    using namespace std;auto g=[](auto&i){int e=i[0].find('e'),n=0,y=0,h=0,o,j,c,x,t=0;for(auto&a:i)t=a.L>t?a.L:t;for_each(i.B,i.end(),[&i,t](string&s){s.resize(t);});srand(time(0));vector<int>s,l;for(j=0;j<i.T;++j){C(S)y)++n;C(89)0)y=j;C(35)h){h=j;for(int d=0;d<i[j].T;++d)if(i[j][d]==35)l.push_back(d+1);s.resize(l.T);}if(h)for(c=0;c<l.T;c++)if(i[j][l[c]]!=32)++s[c];C('x')0)x=j;}--x;for_each(l.B,l.end(),[&i,&x,h](int&a){if(U!=32)--U;if(U==10)U=32;for(int b=x;b>h;--b){if(i[b][a]==32&&i[b-1][a]==S){i[b][a]=S;i[b-1][a]=32;}}if(U==S)U=49+rand()%5;});if(i[y-1][e]==S)i[h][l[min_element(s.B,s.end())-s.B]]=S;for(j=1;j<n+2;++j)if(j<y)i[j][e]=S;};
    

    So... some details :

    • You have to pass a std::vector<std::string> ( they will be resized at the same length the longest string is )

    • All lines of # starts at the same y ( vertical ) coordinates, are the same length, and end at the same y ( vertical ) coordinates

    • Assume that the grid have at least 1 # line or more, have one letter e ( one outlet ) at the top, one letter Y

    • Assume that the input is a valid output so the shoppers waiting to be redirected will always be one after another

    Edit : Just saw in the comments of Wheat Wizard's answer that it should support multiple entrances, i will continue to work on that

    HatsuPointerKun

    Posted 2016-02-14T21:43:38.123

    Reputation: 1 891

    Maybe you could make that C macro be #define C(e)i[j].find(e)!=string::npos? – Conor O'Brien – 2017-07-24T20:16:18.690

    My answer supports multiple entrances as a side effect, of it being golfy. Quartata said it would be required, but I don't see it in the question, so as far as I'm concerned you are free to only support a single entrance. – Post Rock Garf Hunter – 2017-07-28T13:07:23.870

    @WheatWizard Well, if i read the question, it says : "The grid starts out with an e, which represents an outlet" and "all of the outlets", so that suggest it can have several entrances – HatsuPointerKun – 2017-07-28T13:54:31.073

    You can change the definition of C(e) to be #define C(e)if(i[j].find(e)!=string::npos and change the calls accordingly. – Zacharý – 2017-09-04T16:49:22.757

    And since length() is only applied on a, you can change L to be defined as a.length(), modifying calls accordingly. In addition, you can move the using namespace std; to the bottom, saving a byte by removing the newline – Zacharý – 2017-09-04T16:59:28.440

    Three things, using namespace std; can be placed on the bottom line to save a byte, and you can remove the space between C(e) and its definition, and all that combined with a ton macro-shenanigans gives 841 bytes

    – Zacharý – 2017-10-05T17:34:56.640

    840 bytes, using #define T.size() and replacing the references accordingly (which means changing every . before T to a space except for i[j].T which becomes i[j]T, saving the byte) – Zacharý – 2018-11-12T14:48:18.297