Bottom part of the Hourglass

14

2

Challenge:

Input: Three integers: bottom-edge length; starting amount of grains of sand; index

Output: Output the state of the bottom part of an hourglass at the given index, based on the given bottom-edge length and amount of grains of sand.

Challenge rules:

  • We simulate the grains of sand with digits 1-9
  • We put the currently remaining amount of grains of sand at the top in the middle, following by a single character of your own choice (excluding digits, whitespaces and new-lines; i.e. -) on the line below it
  • When the hourglass is being filled, we fill it per row, one digit at a time
  • When the sand can go either left or right, we ALWAYS go right (the same applies to balancing the remaining amount of grains of sand above the hour glass)
  • When we've reached 9 it's filled, and we can't fit any more sand at that specific place in the hourglass
  • The amount of grains of sand left are also always rightly aligned
  • Once the bottom halve of the hourglass is completely filled, or the amounts of grains of sand left reaches 0, we can't go any further, and this would be the output for all indexes beyond this point
  • Both 0-indexed or 1-indexed is allowed, and please specify what you've used in your answer.
  • Trailing and leading spaces and a single trailing or leading new-line are optional
  • You are allowed to use any other character instead of a zero to fill up empty spaces of the bottom part of the hourglass (excluding digits, new-lines, or the character you've used as neck), if you choose to display them.
  • The bottom-edge length will always be odd
  • The bottom-edge length will be >= 3; and the amounts of grains of sand >= 0
  • If you want you are also allowed to print all states up to and including the given index
  • You can assume the (0-indexed) index will never be larger than the total amount of grains of sand (so when there are 100 grains of sand, index 100 is the maximum valid index-input).
  • The first index (0 for 0-indexed; 1 for 1-indexed) will output an empty hourglass with the amount of grains of sand above it.

Example: Pictures (or ascii-art) say more than a thousand words, so here is an example:

Input bottom-edge length: 5
Input amount of grains of sand: 100
Instead of a current index, I display all steps here:

Output for all possible indexes with bottom-edge length 5 and amount of grains of sand 100:

 100
  -
  0
 000
00000

  99
  -
  0
 000
00100

  98
  -
  0
 000
00110

  97
  -
  0
 000
01110

  96
  -
  0
 000
01111

  95
  -
  0
 000
11111

  94
  -
  0
 000
11211

  93
  -
  0
 000
11221

  92
  -
  0
 000
12221

  91
  -
  0
 000
12222

  90
  -
  0
 000
22222

  89
  -
  0
 000
22322

  88
  -
  0
 000
22332

  87
  -
  0
 000
23332

  86
  -
  0
 000
23333

  85
  -
  0
 000
33333

  84
  -
  0
 000
33433

  83
  -
  0
 000
33443

  82
  -
  0
 000
34443

  81
  -
  0
 000
34444

  80
  -
  0
 000
44444

  79
  -
  0
 000
44544

  78
  -
  0
 000
44554

  77
  -
  0
 000
45554

  76
  -
  0
 000
45555

  75
  -
  0
 000
55555

  74
  -
  0
 000
55655

  73
  -
  0
 000
55665

  72
  -
  0
 000
56665

  71
  -
  0
 000
56666

  70
  -
  0
 000
66666

  69
  -
  0
 000
66766

  68
  -
  0
 000
66776

  67
  -
  0
 000
67776

  66
  -
  0
 000
67777

  65
  -
  0
 000
77777

  64
  -
  0
 000
77877

  63
  -
  0
 000
77887

  62
  -
  0
 000
78887

  61
  -
  0
 000
78888

  60
  -
  0
 000
88888

  59
  -
  0
 000
88988

  58
  -
  0
 000
88998

  57
  -
  0
 000
89998

  56
  -
  0
 000
89999

  55
  -
  0
 000
99999

  54
  -
  0
 010
99999

  53
  -
  0
 011
99999

  52
  -
  0
 111
99999

  51
  -
  0
 121
99999

  50
  -
  0
 122
99999

  49
  0
 222
99999

  48
  -
  0
 232
99999

  47
  -
  0
 233
99999

  46
  -
  0
 333
99999

  45
  -
  0
 343
99999

  44
  -
  0
 344
99999

  43
  -
  0
 444
99999

  42
  -
  0
 454
99999

  41
  -
  0
 455
99999

  40
  -
  0
 555
99999

  39
  -
  0
 565
99999

  38
  -
  0
 566
99999

  37
  -
  0
 666
99999

  36
  -
  0
 676
99999

  35
  -
  0
 677
99999

  34
  -
  0
 777
99999

  33
  -
  0
 787
99999

  32
  -
  0
 788
99999

  31
  -
  0
 888
99999

  30
  -
  0
 898
99999

  29
  -
  0
 899
99999

  28
  -
  0
 999
99999

  27
  -
  1
 999
99999

  26
  -
  2
 999
99999

  25
  -
  3
 999
99999

  24
  -
  4
 999
99999

  23
  -
  5
 999
99999

  22
  -
  6
 999
99999

  21
  -
  7
 999
99999

  20
  -
  8
 999
99999

  19
  -
  9
 999
99999

So as example:

inputs: 5,100,1
output:
  99
  -
  0
 000
00100

Same example with another valid output format:
  99
  ~
  . 
 ...
..1..

General rules:

  • This is , so shortest answer in bytes wins.
    Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
  • Standard rules apply for your answer, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters, full programs. Your call.
  • Default Loopholes are forbidden.
  • If possible, please add a link with a test for your code.
  • Also, please add an explanation if necessary.

Test cases:

INPUTS: bottom-edge length, amount of grains of sand, index (0-indexed)

inputs: 5,100,1
output:
  99
  -
  0
 000
00100

inputs: 5,100,24
output:
  76
  -
  0
 000
45555

inputs: 5,100,100
output:
  19
  -
  9
 999
99999

inputs: 5,10,15
output:
  0
  -
  0
 000
22222

inputs: 3,30,20
output:
 10
 -
 0
677

inputs: 3,3,0
 3
 -
 0
000

inputs: 9,250,100
   150
    -
    0
   000
  00000
 2333332
999999999

inputs: 9,225,220
    5
    -
    4
   999
  99999
 9999999
999999999

inputs: 13,1234567890,250
  1234567640
      -
      0
     000
    00000
   0000000
  344444443
 99999999999
9999999999999

inputs: 25,25,25
             0
             -
             0
            000
           00000
          0000000
         000000000
        00000000000
       0000000000000
      000000000000000
     00000000000000000
    0000000000000000000
   000000000000000000000
  00000000000000000000000
 1111111111111111111111111

Kevin Cruijssen

Posted 2018-01-25T08:30:03.917

Reputation: 67 575

1For 5,100,10000 why does 20+9+9+9+9+9+9+9+9+9 = 101? – Neil – 2018-01-25T08:57:55.577

@Neil I'll change the rules a bit so the index can never go beyond the total sum. Probably better to understand. – Kevin Cruijssen – 2018-01-25T09:03:26.310

3Related – Laikoni – 2018-01-25T09:38:11.163

is the first input always an odd number? – Brian H. – 2018-01-25T15:47:30.047

@BrianH. "The bottom-edge length will always be odd" I realize I have a bit too much rules in this challenge, so I can understand you've read past it. :) – Kevin Cruijssen – 2018-01-25T16:12:19.003

Answers

3

05AB1E, 68 63 59 57 56 bytes

IÅÉÅ9[DOO²Q#ćD_Piˆëć<¸«¸ì]ćā<ΣÉ}2äćR¸ì˜è¸ì¯ìJDSOIα'-‚ì.C

Try it online!

Explanation

IÅÉÅ9
We initialize the stack with a list of list of 9's.
Each list represents a row so the length of each list is odd and the length of the last list is equal to the first input.
An input of 5 would result in [[9], [9, 9, 9], [9, 9, 9, 9, 9]]

[DOO²Q#ćD_Piˆëć<¸«¸ì]
We then iterate over these lists decrementing elements in a list until the list consists only of zeroes, then moving on to the next. We stop when the total sum equals the second input.

[     #              ]   # loop until
 DOO                     # the sum of the list of lists
    ²Q                   # equals the second input
        ć                # extract the first list
         D_Pi            # if the product of the logical negation of all elements is true
             ˆ           # add the list to the global list
              ë          # else
               ć<        # extract the head and decrement it
                 ¸«      # append it to the list
                   ¸ì    # and prepend the list to the list of lists

Now we need to unsort the final list simulating removing elements from alternating sides instead of left-to-right as we have been doing.

ć                   # extract the row we need to sort
 ā<                 # push a list of indices of the elements [0 ... len(list)-1]
   ΣÉ}              # sort it by even-ness
      2äćR¸ì˜       # reverse the run of even numbers
                    # the resulting list will have 0 in the middle,
                      odd number increasing to the right and
                      even numbers increasing to the left
             è      # index into our final row with this
              ¸ì¯ì  # reattach all the rows to eachother

Now we format the output correctly

J              # join list of lists to list of strings
 DSOIα         # calculate the absolute difference of sum of our triangle and the 3rd input
      '-‚ì     # pair it with the string "-" and append to the list of rows
          .C   # join by newlines and center each row

Emigna

Posted 2018-01-25T08:30:03.917

Reputation: 50 798

Really? It was this complicated? – Magic Octopus Urn – 2018-01-29T14:43:39.997

@MagicOctopusUrn: You are very welcome to outgolf me :) Some things about this method became a bit messy due to language quirks that I haven't found a better way around. Maybe there's a better way altogether? Maybe something more mathematical? – Emigna – 2018-01-29T18:34:29.120

I was thinking about using binary numbers somehow... didn't think it out fully, didn't have a spare hour. – Magic Octopus Urn – 2018-01-29T18:58:12.910

It has been awhile since I've tried to outgolf one of your solutions that's more than 20 bytes. Bit ashamed to admit it, but when I see your answers I usually don't waste the time trying to find improvements anymore; because usually I am unable to find any hah! – Magic Octopus Urn – 2018-01-31T18:29:49.280

@MagicOctopusUrn: Too bad. You usually manage to come up with interesting alternatives (and/or improvements) to my solutions. Large programs in golfing languages are certainly more difficult to take the time to work on for sure. – Emigna – 2018-01-31T18:58:49.993

You're slaying it recently, seriously I've been trying recently to find improvements on your newer answers and I think they're borderline optimized lol. – Magic Octopus Urn – 2018-01-31T19:29:08.277

@KevinCruijssen: Explanation added. – Emigna – 2018-02-06T12:12:27.420

5

Clean, 305 289 bytes

import StdEnv
@[h:t]|all((==)9)h|t>[]=[h: @t]=[h]
#s=length h/2
#m=hd(sort h)+1
=[updateAt(hd[e\\e<-flatten[[s+i,s-i]\\i<-[0..s]]|h!!e<m])m h:t]
$a b c=flatlines(map(cjustify(a+1))[fromString(fromInt(b-c)),['-']:reverse(map(map(toChar o(+)48))((iterate@[repeatn(a-r)0\\r<-[0,2..a]])!!c))])

Try it online!

Οurous

Posted 2018-01-25T08:30:03.917

Reputation: 7 916

1@KevinCruijssen Fixed. – Οurous – 2018-01-25T09:36:05.107

1

Perl 5, 301 bytes

($x,$t,$u)=<>;$s=$x;$t-=$g=$t>$u?$u:$t;while($s>0){@{$a[++$i]}=((0)x$s,($")x($x-$s));$a[$i][$_%$s]++for 0..($f=$g<$s*9?$g:$s*9)-1;$g-=$f;$s-=2}say$"x(($x-length($g+=$t))/2+.5),$g,$/,$"x($x/2),'-';while(@b=@{pop@a}){for($i=1;$i<@b;$i+=2){print$b[-$i]}print$b[0];for($i=1;$i<@b;$i+=2){print$b[$i]}say''}

Try it online!

Xcali

Posted 2018-01-25T08:30:03.917

Reputation: 7 671

1

Charcoal, 68 63 62 bytes

NθNηNζF⊘⊕θF⁹F⁻θ⊗ι«J⊘⎇﹪λ²⊕λ±λ±ι≔¬¬ζλ↑I⁺λIKK≧⁻λη≧⁻λζ»↑-M⊘⊖LIη←Iη

Try it online! Link is to verbose version of code. Edit: Saved 5 bytes by removing the now-unnecessary index range check. Explanation:

NθNηNζ

Input the length into q, the number of grains of sand into h and the index into z.

F⊘⊕θF⁹F⁻θ⊗ι«

Loop over the (q+1)/2 rows (from bottom to top), then 9 grains in each cell in the row, then loop over the digits in the row.

J⊘⎇﹪λ²⊕λ±λ±ι

Jump to the digit.

≔¬¬ζλ↑I⁺λIKK≧⁻λη≧⁻λζ»

If possible, distribute a grain of sand to this digit, decrementing the amount of sand and index left. If we've passed the index, this still converts spaces to zeros, filling the hourglass. The digit is printed upwards because this means that the cursor will be on the neck after the last digit.

↑-

Print the neck.

M⊘⊖LIη←Iη

Centre and print the amount of sand remaining.

Neil

Posted 2018-01-25T08:30:03.917

Reputation: 95 035