How did the chicken cross the road?

16

2

Cluck cluck. No one knows why the chicken crossed the road, maybe there was a good looking rooster on the other side. But we can figure out how. Write a program, that, left to right, crosses this (or any) "road".

1356 | 1738
3822 | 1424
3527   3718
9809 | 5926
0261 | 1947
7188   4717
6624 | 9836
4055 | 9164
2636   4927
5926 | 1964
3144 | 8254

Your program "crosses" it, moving left to right. You start on any number on the leftmost column you like. From there, you can move to any adjacent character to the right. If you started at the top left corner, 1, you could go to either 3 or 8. Every number you go to, including the starting number, is added to a sum. Spaces do not add to your sum. "|" forces you to move up or down, rather than somewhere to the right. (You CAN'T move forward on this character) Your goal is to get to the other side with the smallest possible sum. Your program must print out the sum at the end, and it must be able to solve any road. Preferably, it could also have input for a road, but it's not required. Your program must print both the path and the sum. Fewest bytes of code wins.

To clarify, you can move diagnally unless you are on a vertical bar. You can only move up and down when you are on a vertical bar.

For a clearer specification of roads, it is basically a string of text (Or an array of columns or rows, should you prefer to think that way) that follows the rules of the characters, and there can't be anything BUT those characters in the road. There can be any number, a space, a bar ("|"), or a newline. If a road was paved by a drunk guy, as in ProgrammerDan's answer, it is still a valid road, and your program must be able to solve such a road. It is not considered a road if it is impossible to get to the other side (For example, there is no way out of a straight line of bars).

Your program is not required to determine if a road is invalid.

Key:
Any number - adds the number to your sum, move forward.
Space - Move forward, nothing is added to your sum.
"|" - Move up or down, nothing is added to your sum.

EDIT: An example solution, as suggested. I can't make a horribly big one, I can't get on an IDE to solve it for me ATM.

Take this small road:

9191 | 8282
1919 | 2727
5555   5555

The solution would be a path of 1, 1, 1, 1, space, divider, divider, space, space, 2, 2, 2, 2 for a total of 12.

EDIT #2: The solution to the first road on this question, as determined by Geobits and peoples programs, is 0,2,0,1, , , ,1,4,1,4 for a sum of 13.

CaffeineToCode

Posted 2015-09-18T18:43:22.583

Reputation: 271

4Could you include at least one test case with a correct solution? Also, could there be more than three | in a row? – Martin Ender – 2015-09-18T18:48:37.060

Yes, as long is there is a space somewhere on the line. I'm on a mobile device ATM, so I can't write a program to find the solution for me. I'll post a solution to the current example when I can get on an IDE. – CaffeineToCode – 2015-09-18T18:50:22.927

When you say you can move to either 3 or 8 from the 1, does this include the 3 below the 1? Or can we not move straight up or down unless we're left-adjacent to a vertical bar? – mbomb007 – 2015-09-18T18:54:44.467

If I'm understanding this correctly, for example, the upper-right 1738 will never have the 1 be touched, because the chicken's "path" will exit the space at the 3 and the 1 isn't adjacent to the space, right? – AdmBorkBork – 2015-09-18T18:56:11.907

@mbomb you can only move straight down when you're on a vertical bar. – CaffeineToCode – 2015-09-18T18:57:49.650

1@timmy you can move diagonally, as long as it is moving forward. It can be touched with a couple of diagonal movements. – CaffeineToCode – 2015-09-18T18:58:41.773

To be clear, it doesn't matter if your path has more spaces/bars than necessary at all? Like in your example, you could avoid the bar altogether with diagonal movement and get the same sum with one less "move". – Geobits – 2015-09-18T19:02:16.363

Correct, spaces/bars do not affect your sum. Moves don't matter. – CaffeineToCode – 2015-09-18T19:03:02.943

3@mbomb007 If starting at the top corner. Since you can start on any in the left column, you can get 0,2,0,1, , , ,1,4,1,4 -> 13 – Geobits – 2015-09-18T19:07:10.150

Since it looks like you can walk up/down on the spaces, it doesn't really matter where the gaps in the vertical line are, does it? – Reto Koradi – 2015-09-19T03:34:09.213

1Yes, it does. You can only move up or down on the bars, so you can only get out of them through a space. – CaffeineToCode – 2015-09-19T03:35:40.230

Are "roads" a fixed width of 4 per side? If not, are both sides always equal width? – Brian Tuck – 2015-09-22T17:10:31.663

@Brian No, there is no set width. – CaffeineToCode – 2015-09-22T22:03:28.390

1For the output, simply the cost suffices, or does the entire path need to be output? – ProgrammerDan – 2015-09-24T18:40:41.713

@ProgrammerDan it has to output both. – CaffeineToCode – 2015-09-24T19:15:20.573

Are we guaranteed that the | pieces will all line up with each other? – dfeuer – 2015-09-24T19:24:01.693

In your small test example, I don't see how you can do it with just three spaces while following the rules. Doesn't it take four? – dfeuer – 2015-09-24T19:27:11.027

@dfeuer fixed it. – CaffeineToCode – 2015-09-24T19:32:23.997

And also @dfeuer no, it is not grunted to line up. Perhaps the guy painting the lines was drunk. – CaffeineToCode – 2015-09-24T19:33:21.663

Another question: Is the road guaranteed to be the same width everywhere, or might different lines in the input have different lengths? – dfeuer – 2015-09-24T19:47:00.123

Nope. The only things that are certain is the rules of the characters. – CaffeineToCode – 2015-09-24T20:04:13.433

Mean, I love it! Looking forward to some excellent answers emerging. – ProgrammerDan – 2015-09-24T21:05:38.183

Answers

3

Pyth, 168 143 141 bytes [now Drunken Road compatible]

My test case works, but because of a misunderstanding on my part, it won't work properly with the initial example. I'm working on fixing it.

Now working for original example and drunken roads

Some REALLY slightly less ugly code:

=Z.dC,++\ `MUT\|++0UT=^T5Ltu+G]?&qeeG\|<heGhH+eGeHHtb,0hbKhohNum++hed@ZhhdtedC,H_y_y.b+N]YmhohNd.:++TGT3HCm.[d\ lh.MlZ.z.z*hl.z]]0j\,t.sK\ hK

Test it Here

I tested it on a 10+9 x 40 road.

6417443208|153287613
8540978161|726772300
7294922506 263609552
0341937695 498453099
9417989188 370992778
2952186385|750207767
7049868670 756968872
1961508589|379453595
0670474005 070712970
4817414691|670379248
0297779413|980515509
6637598208 090265179
6872950638 767270459
7375626432 439957105
1387683792|544956696
6974831376 545603884
0949220671|632555651
3952970630|379291361
0456363431|275612955
2973230054|830527885
5328382365|989887310
4034587060 614168216
4487052014|969272974
5015479667 744253705
5756698090|621187161
9444814561|169429694
7697999461|477558331
3822442188 206942845
2787118311|141642208
2669534759 308252645
6121516963|554616321
5509428225|681372307
6619817314|310054531
1759758306 453053985
9356970729|868811209
4208830142 806643228
0898841529|102183632
9692682718|103744380
5839709581|790845206
7264919369|982096148

Brian Tuck

Posted 2015-09-18T18:43:22.583

Reputation: 296

Just a note, getting a "IndexError: list index out of range" when running using the test suite provided. – ProgrammerDan – 2015-09-24T14:22:39.123

@ProgrammerDan so do I. – CaffeineToCode – 2015-09-24T14:55:30.607

@ProgrammerDan Are you using the test link? "Compiler last updated: 21 Sep 2015 UTC" I've tried in FireFox and Chrome, both with the link and copy/pasting. I'd really like to figure this out, so any help would be appreciated. – Brian Tuck – 2015-09-24T18:17:13.677

@BrianTuck Not sure what changed, but is working now. – ProgrammerDan – 2015-09-24T18:40:13.877

For what it's worth, I made a change to Pyth that might have broken things ~12 hours ago, and reverted it ~4 hours ago. – isaacg – 2015-09-24T20:30:54.087

Your answer and mine match. – ProgrammerDan – 2015-09-25T03:07:12.100

@BrianTuck taking OP literally, the road rows might not all be the same length, and might not all start or end with numbers. I've put an example with my code illustrating this and its effect, I'd love to see a Pyth way of addressing it! – ProgrammerDan – 2015-09-25T04:50:16.290

It doesn't seem to like ProgrammerDan's drunk road. – CaffeineToCode – 2015-09-25T06:08:30.837

1@CaffeineToCode true, but the concept of a "drunk road" was added after I submitted. It would have been helpful to have known what constituted a road. Based on the examples I assumed 2 sides with a dividing column – Brian Tuck – 2015-09-25T06:32:52.223

@BrianTuck I didn't specify that they had dividing columns, only the keys. Granted I should have. This is actually my first Code Golf question. I've learned a lot from this. – CaffeineToCode – 2015-09-25T13:26:34.943

1@CaffeineToCode One of the best ways to write a good question is just to write more examples -- even without solution. If variable width or multi-lane roads were valid, one "crazy" example would have illustrated it without any additional descriptive text. – ProgrammerDan – 2015-09-25T15:57:18.140

@CaffeineToCode It's a fun first question. Sorry for my complaining, but I'm new to Pyth and have little experience with functional programming. Rewriting my program was quite a task, and I'm a bit daunted by the thought of rewriting it again. – Brian Tuck – 2015-09-25T17:38:39.070

1@ProgrammerDan You asked for it. Mine is now DR-compatible (and shorter... guess I'm catching on) – Brian Tuck – 2015-09-25T21:18:56.343

4

Java, 955 bytes

Obviously not going to win any awards, being Java and all, but I love this problem and wanted to throw in my own entry.

Features and limits:

  • Can support irregular roads (super drunk!) including variable widths, complex lines, etc.
  • Expects road to be input as parameters on execution; the ungolfed version also supports reading from stdin, but since input method wasn't specified the golfed version expects smallest!
  • Uses some dynamic programming technique I haven't used in, oh, 6 years or so to efficiently solve in O(n*m) time, where n is rows and m is columns.
    • Solves from right to left, marking the best direction to take from the current index to the next index.
    • "lines" are handled by resolving their column, then addressing them if reachable on the next column over. They resolve by storing direction up or down, with the cost of the eventually reachable non-line.
  • Tracks, but doesn't print (in golf'd version) the starting index of the best solution.

Ok, enough jibba jabba. Golfed version:

class C{public static void main(String[]a){int n=a.length,m=0,i=0,j=0,h=0,p=0,q=0,s=0,t=0,b=-1,c=2147483647,x=0,y=0;char[][]r=new char[n][];char u;for(String k:a){j=k.length();m=(j>m)?j:m;}for(String k:a)r[i++]=java.util.Arrays.copyOf(k.toCharArray(),m);int[][][]d=new int[n][m][2];for(j=m-1;j>=0;j--){for(i=0;i<n;i++){u=r[i][j];p=(u=='\0'||u==' '||u=='|'?0:u-'0');if(j==m-1)d[i][j][1]=p;else{if(u=='|')d[i][j][0]=-1;else{for(h=-1;h<2;h++){x=i+h;y=j+1;if(x>=0&&x<n){if(d[x][y][0]==-1){s=x-1;while(s>=0&&r[s][y]=='|')s--;t=x+1;while(t<n&&r[t][y]=='|')t++;if((s>=0&&t<n&&d[s][y][1]<d[t][y][1])||(s>=0&&t>=n)){t=d[s][y][1];s=4;}else{s=6;t=d[t][y][1];}d[x][y][0]=s;d[x][y][1]=t;}q=d[x][y][1]+p;if(d[i][j][0]==0||q<d[i][j][1]){d[i][j][0]=h+2;d[i][j][1]=q;}}}}}if(j==0&&(b<0||d[i][j][1]<c)){b=i;c=d[i][j][1];}}}String o="";i=b;j=0;while(j<m){u=r[i][j];if(u=='\0')j=m;else{o+=u+",";h=d[i][j][0]-2;if(h>1)i+=h-3;else{i+=h;j++;}}}System.out.println(o+"\b:"+c);}}

As per my habit, github with the ungolfed code.

Solution for "first" road:

$ java C "1356 | 1738" "3822 | 1424" "3527   3718" "9809 | 5926" "0261 | 1947" "7188   4717" "6624 | 9836" "4055 | 9164" "2636   4927" "5926 | 1964" "3144 | 8254"
0,2,0,1, , , ,1,4,1,4:13

Second example:

$ java C "9191 | 8282" "1919 | 2727" "5555   5555"
1,1,1,1, ,|,|, , ,2,2,2,2:12

Brian Tuck's sample:

$ java C "6417443208|153287613" "8540978161|726772300" "7294922506 263609552" "0341937695 498453099" "9417989188 370992778" "2952186385|750207767" "7049868670 756968872" "1961508589|379453595" "0670474005 070712970" "4817414691|670379248" "0297779413|980515509" "6637598208 090265179" "6872950638 767270459" "7375626432 439957105" "1387683792|544956696" "6974831376 545603884" "0949220671|632555651" "3952970630|379291361" "0456363431|275612955" "2973230054|830527885" "5328382365|989887310" "4034587060 614168216" "4487052014|969272974" "5015479667 744253705" "5756698090|621187161" "9444814561|169429694" "7697999461|477558331" "3822442188 206942845" "2787118311|141642208" "2669534759 308252645" "6121516963|554616321" "5509428225|681372307" "6619817314|310054531" "1759758306 453053985" "9356970729|868811209" "4208830142 806643228" "0898841529|102183632" "9692682718|103744380" "5839709581|790845206" "7264919369|982096148"
2,1,0,1,5,1,2,1,1,1, ,1,0,1,2,1,2,3,0,1:26

"Drunkified" Brian's example:

6417443208|153287613
8540978161|726772300
7294922506 263609552
0341937695 498453099
9417989188 370992778
2952186385|750207767
7049868670 756968872
1961508589|379453595
0670474005 070712970
4817414691|670379248
0297779413|980515509
6637598208 090265179
6872950638 767270459
7375626432 439957105
1387683792|544956
697483176 5456034
09492201|6325551
395297030|3792913
 456363431|275612
  73230054|830527885
    8382365|989887310
    4587060 614168216
  87052014|96927297
 50479667 7442537
57566980 | 621187161
944481456 | 169429694
7697999461|477558331
3822442188 206942845
2787118311|141642208
2669534759 308252645
6121516963|554616321
5509428225|681372307
6619817314|310054531
1759758306 453053985
9356970729|868811209
4208830142 806643228
0898841529|102183632
9692682718|103744380
5839709581|790845206
7264919369|982096148
$ java C "6417443208|153287613" "8540978161|726772300" "7294922506 263609552" "0341937695 498453099" "9417989188 370992778" "2952186385|750207767" "7049868670 756968872" "1961508589|379453595" "0670474005 070712970" "4817414691|670379248" "0297779413|980515509" "6637598208 090265179" "6872950638 767270459" "7375626432 439957105" "1387683792|544956" "697483176 5456034" "09492201|6325551" "395297030|3792913" " 456363431|275612" "  73230054|830527885" "    8382365|989887310" "    4587060 614168216" "  87052014|96927297" " 50479667 7442537" "57566980 | 621187161" "944481456 | 169429694" "7697999461|477558331" "3822442188 206942845" "2787118311|141642208" "2669534759 308252645" "6121516963|554616321" "5509428225|681372307" "6619817314|310054531" "1759758306 453053985" "9356970729|868811209" "4208830142 806643228" "0898841529|102183632" "9692682718|103744380" "5839709581|790845206" "7264919369|982096148"
 , , , ,0,5,2,0,1, , , ,1,1,1,3,2:16

Solution visualized:

09492201|6325551
395297030|3792913
\456363431|275612
 \73230054|830527885
  \ 8382365|989887310
   \4\87060 614168216
  87/5--\4|96927\97
 50479667\74425/7
57566980 |\62-/87161
944481456 |\/69429694
7697999461|477558331

Enjoy!

Edit: Now I'm just showing off (two roadways merge! Can he make it?)

948384 | 4288324   324324 | 121323
120390 | 1232133   598732 | 123844
 293009 | 2394023 432099 | 230943
 234882 | 2340909 843893 | 849728
  238984 | 328498984328 | 230949
  509093 | 904389823787 | 439898
   438989 | 3489889344 | 438984
   989789 | 7568945968 | 989455
    568956 | 56985869 | 568956
    988596 | 98569887 | 769865
     769879 | 769078 | 678977
     679856 | 568967 | 658957
      988798 | 8776 | 987979
      987878 | 9899 | 989899
       999889 |    | 989899
       989999 |    | 989999
        989898 |  | 998999
        989999 |  | 999999
         989998 || 899999
         989998 || 998999

Solution:

$ java C "948384 | 4288324   324324 | 121323" "120390 | 1232133   598732 | 123844" " 293009 | 2394023 432099 | 230943" " 234882 | 2340909 843893 | 849728" "  238984 | 328498984328 | 230949" "  509093 | 904389823787 | 439898" "   438989 | 3489889344 | 438984" "   989789 | 7568945968 | 989455" "    568956 | 56985869 | 568956" "    988596 | 98569887 | 769865" "     769879 | 769078 | 678977" "     679856 | 568967 | 658957" "      988798 | 8776 | 987979" "      987878 | 9899 | 989899" "       999889 |    | 989899" "       989999 |    | 989999" "        989898 |  | 998999" "        989999 |  | 999999" "         989998 || 899999" "         989998 || 998999"
 ,2,0,3,0,0, ,|,|, ,|,|, ,|,|, ,|,|, ,|,|, ,|,|, ,|,|, , , , , , , ,|, ,|, ,|, ,|, ,|, ,|, ,|,|, , ,1,0,7,2:15

(bonus: path from ungolfed):

$ java Chicken < test5.txt
best start: 3 cost: 15
  -> 2 -> 0 -> 3 -> 0 -> 0 ->   -> | -> | ->   -> | -> | ->   -> | -> | ->   -> | -> | ->   -> | -> | ->   -> | -> | ->
  -> | -> | ->   ->   ->   ->   ->   ->   ->   -> | ->   -> | ->   -> | ->   -> | ->   -> | ->   -> | ->   -> | -> | ->
  ->   -> 1 -> 0 -> 7 -> 2 -> 15
/ -> - -> - -> \ -> / -> / -> - -> , -> , -> - -> , -> , -> - -> , -> , -> - -> , -> , -> - -> , -> , -> - -> , -> , ->
- -> , -> , -> / -> \ -> - -> - -> - -> / -> / -> ^ -> / -> ^ -> / -> ^ -> / -> ^ -> / -> ^ -> / -> ^ -> / -> , -> , ->
/ -> - -> \ -> \ -> - -> \ -> across

Details on Algorithm

A more complete explanation of the Dynamic Programming technique I employed was requested, so here goes:

I'm using a mark-and-precompute method of solution. It has a proper name, but I've long since forgotten it; perhaps someone else can offer it?

Algorithm:

  • Starting at the right-most column and progressing to the left, compute the following about each cell in the column:
    • The summation of lowest cost movement, defined as current cell cost + lowest cost cell reachable in the next column
    • The movement action to take to achieve this lowest cost, as simply a valid move from this cell to another single cell.
  • Pipes are deferred. To resolve a pipe, you need to have the full column computed, so we don't compute pipes until the next column.
    • When determining the lowest cost of a cell to the left of a pipe, we first compute the best direction to travel along the pipe -- it will always resolve to either up, or down, so we compute it once.
    • We then store, as with all other cells, the best cost (defined as the cost of the cell we reach by travelling either up or down on the pipe) and the direction to travel to reach it.

Notes:

That's it. We scan from top to bottom, right to left, once; the only cells touched (potentially) more then once are pipes, however, each pipe is only "solved" once, keeping us within our O(m*n) window.

To handle "odd" map sizes, I chose to simply pre-scan and normalize lengths of rows by padding with null characters. Null characters count as "zero cost" moves same as pipes and spaces. Then, in printing the solution, I stop printing costs or moves when either the edge of the normalized road is reached, or a null character is reached.

The beauty of this algorithm is it's very simple, applies the same rules to every cell, producing a full solution by solving O(m*n) sub-problems, and in terms of speed is rather fast. It does trade off memory, creating effectively two copies in memory of the roadway map, the first to store "best cost" data and the second to store "best move" data per cell; this is typical for dynamic programming.

ProgrammerDan

Posted 2015-09-18T18:43:22.583

Reputation: 1 129

Could you explain your approach to lines a bit more? I also attempted a (somewhat different) dynamic programming approach, but got stuck figuring those out. I've also considered an incremental (row by row) approach to deal with extremely long roads that are not too wide without using too much memory; do you know if there's a way to do that in under O(m^2*n) time? – dfeuer – 2015-09-25T16:27:35.290

@dfeuer It's all about the tradeoffs, to be sure. None of the row-by-row approaches I considered were able to handle all permutations of input without succumbing to O(m^n) time at some point; this is a column-by-column problem by construction (movement, largely, goes from left-to-right -- efficient DP solution goes from right-to-left).

You might be able to do an O(m*n) approach solving row-by-row with simple look-behind and deferred look ahead, but you're greatly increasing complexity without likely saving a lot of memory. – ProgrammerDan – 2015-09-25T17:55:32.903

What I was thinking was that if I'm not mistaken you need only keep track of the best path thus far and, for each square in the most recently processed row, the best known paths from the left edge, to the right edge, and to each square to its right in the same row. Is that wrong? – dfeuer – 2015-09-25T18:02:11.837

I've added an explanation. The technique I use is far simpler; it's a purely cell-local solver. You only need to know the best route leading out of each cell, each cell doesn't need to know the best way to get to it, only the best way to leave. Once you have all those computed, assuming you've kept track of the cost as you've gone, you can simply pick the "lowest cost" starting position as you've already computed the total, best route, cost. – ProgrammerDan – 2015-09-25T18:10:24.820

1Thanks! You can shorten your code a drop by defining c as -1>>>1. – dfeuer – 2015-09-25T18:36:10.137

Awesome, I'll toss that change up tonight. Good luck with your implementation! What language are you targeting, if you don't mind spoiling a little? :) – ProgrammerDan – 2015-09-25T18:49:04.140

1I'm targeting Haskell, which will make it hard to compete for length, but it's what I know best by far. – dfeuer – 2015-09-25T18:51:32.580

@ProgrammerDan My method is similar, but progresses left-to-right. I wonder if right-to-left would make it easier to handle lines – Brian Tuck – 2015-09-25T21:23:42.993

@BrianTuck Hard to say. I know in my "thinkings" LTR didn't work, because you make local decisions on incomplete knowledge, whereas RTL makes local decisions on complete knowledge. LTR without full lookahead (enumeration) will make locally-optimal decisions but potentially poor global decisions; so RTL in my thinking is superior. TL;DR -- LTR is a poly-time estimator (inaccurate but fast); RTL is a poly-time solver (accurate and fast). In either case you'd need a way to "normalize" line length. – ProgrammerDan – 2015-09-25T21:48:24.950

@ProgrammerDan Since Pyth works best for functional programming, I couldn't really use a matrix-based approach, so I basically use a complex reduce function on the list of columns. – Brian Tuck – 2015-09-25T21:59:43.140