# Simulate weathering of a rock

Inspired by my geography class, Sandboxed

Simulate weathering / erosion.

### Input

Input will be given as a string of any 2 characters (or see below) you like in the shape of the rock (here i use spaces and hashes):

   ###
####
#####
#######
#######
########


Or if your language doesn't support strings, a square matrix of 1s and 0s, a matrix of chars, whatever makes your answer more golfier.

# Process

The rock will erode until it disappears completely. Lets take example of input:

    ##
## ### #
#########
###########


First we find which part of the rock is exposed (that is there is no rock particle directly above / below / left / right) to the air (i use @ to show such particles here):

    @@
@@ @#@ @
@##@###@@
@########@@


NOTE: The bottom most rock particles are touching the ground and they are not touching air, hence we don't count these particles.

Then we randomly (50% chance individually for each particle) remove the rock particles (here #) (apply gravity similar to this challenge that are exposed to the air:

    #
##
## ### #
##########


And be repeat the process until the rock disappears and output the rock in between each iteration (including the original input). In this case we output:

    ##
## ### #
#########
###########
#
##
## ### #
##########

## ##
#########

#  #
## #### #

#
#  # # #

#    #


This is code-golf, answer in the shortest amount of bytes wins.

• Apply gravity... But a rock in shape "###/#.#/###" is possible in real life. And the # in top middle will not fail down.
– tsh
Dec 6, 2021 at 10:04
• Can we output with additional leading/trailing spaces (e.g. input "# #\n# #\n###" would be output in the first iteration as " # # \n # # \n ### " - the output will always be two wider than the input with padded spaces)? Dec 6, 2021 at 11:52
• @KevinCruijssen Yes, you can Dec 6, 2021 at 12:41
• @tsh But then you can technically have some rock like '##\n\n###' which is not possible in real life. Dec 6, 2021 at 12:43
• @Edward what do you mean? Dec 7, 2021 at 4:44

# Charcoal, 58 bytes

≔Ｅθ⁰ηＷＳＵＭη⁺κ⁼#§ιλ⊞η⁰Ｗ⌈η«Ｍι↓↑Ｅη×#κ⸿ＵＭη↨¹Ｅκ∨‹μ⌊⟦§η⊖λ⊖κ§η⊕λ⟧‽


Try it online! Link is to verbose version of code. Assumes input is a rectangular newline-terminated list of strings. Explanation:

≔Ｅθ⁰ηＷＳＵＭη⁺κ⁼#§ιλ


Calculate the height of each column of the rock.

⊞η⁰


Ｗ⌈η«


Repeat until the rock has been eroded away.

Ｍι↓


Leave space to display the rock.

↑Ｅη×#κ


Output the rock.

⸿


Leave a blank line between rocks. (Otherwise they just crash into each other making the output impossible to interpret.)

ＵＭη↨¹Ｅκ∨‹μ⌊⟦§η⊖λ⊖κ§η⊕λ⟧‽


For each column, for each particle, check whether it's exposed, and add up all of the unexposed particles and randomly the exposed particles.

# 05AB1E (legacy), 42 bytes

0ì€Ć[ø€{ø=ÐSO_#ø‚εεDTÂ‚00.:ø}}ø‚øεøεSÚΩ}J


I/O as a list of equal-sized strings, with digits 0 for spaces and 1 for rocks. The output will be two wider than the input, due to a leading/trailing column of spaces/0s.

Uses the legacy version of 05AB1E, because ø works on lists of strings. In the new 05AB1E version, most of the ø should be €SøJ instead.

Explanation:

0ì€Ć                   # Add a leading/trailing 0 to each line of the (implicit)
# input-list:
0ì                     #  Prepend a 0 in front of each line
€                    #  Map over each line:
Ć                   #   Enclose it, appending its own head
[                      # Then start an infinite loop:
ø€{ø                  #  Apply gravity:
ø                     #   Zip/transpose; swapping rows/columns
€{                   #   Sort each row
ø                  #   Zip/transpose back
=                 #  Print the result with newline (without popping)
Ð                 #  Triplicate the current result
S                #  Convert the top one to a flattened list of digits
O               #  Sum this list
_              #  If it's 0:
#             #   Stop the infinite loop
ø                #  Zip/transpose the top; swapping rows/columns
‚               #  Pair it with its untransposed list
ε              #  Map over this pair:
ε             #   Map over each row:
D            #    Duplicate the current row
T           #    Push 10
Â          #    Bifurcate it; short for Duplicate & Reverse copy
‚         #    Pair them together: [10,"01"]
00.:     #    Replace all "10" and "01" in the copy with "00"
ø    #    Create cell-pairs of the row and modified row
}}             #  Close both maps
#  Pop and push both separated to the stack
ø           #  Transpose the top copy back
‚          #  Pair them back together
ø         #  Transpose this pair of matrices
ε        #  Map over each pair of rows
ø       #   Zip/transpose to pair together cell-pairs
ε      #   Map over each pair of cells-pairs:
S     #    Convert it to a flattened list of four digits
Ú    #    Uniquify it
Ω   #    Pop and push a random value from this list
}      #   Close the inner map
J     #   Join the list of characters back to a string-line


I'm not happy with }}ø‚øεøεSÚΩ}J at all, but I'm unable to find something shorter to concat the values of two matrices. Adding values of two matrices together is no problem, since that is just +, but concatenation on the other hand.. (An equal-bytes alternative for this portion could be }}øδ+εNèεÚΩ}J.)
Feel free to try and find something shorter here.

# Perl 5 + -n0, 99 bytes

I'm hoping to continue working on this tonight, but this is a start (which I think covers the requirements?)

Accepts a rectangular multi-line string of 1s and 0s which are transliterated from # and space in the link.

while(/1/){say;/
/;($-)=@-;s/1(?!1)|(?<!1)1|(?<=0.{$-})1/0|rand 2/ges;1while s/1(.{$-})0/0${1}1/gs}


Try it online!

• @PyGamer0 Hmmm, it should be, it includes this code: Try it online! Did you see a specific example that was broken? Dec 6, 2021 at 13:58
• Seems to be working, my eyes have deceived me. Dec 6, 2021 at 14:01

# Python 3, 356 bytes

import random as r,re
y=lambda _:[' ','#'][r.choice([0,1])]
g=lambda x:[*map(''.join,zip(*[(' '*(len(x)-i.count('#')))+('#'*i.count('#'))for i in zip(*x)]))]
f=lambda x:[w:=g([re.sub('#' if not i else'#(?=[^#])|(?<=[^#])#',y,a)for i,a in enumerate(x)])]+(f(w)if any(i.strip()for i in w)else[])
h=lambda x:[*map('\n'.join,f([f' {i} 'for i in x.split('\n')]))]