Hotel room numbering
CJam, 34 31 bytes
qN/W%zSf-La%{_{s'*&}#_)@@=}3*;\
This requires the input to be padded to a rectangle with spaces.
Try it online! Alternatively, run all test cases.
Explanation
qN/ e# Read input and split into lines.
W%z e# Rotate 90° counter-clockwise.
Sf- e# Remove all spaces from the rows.
La% e# Split into buildings. We've now got a 3D array of rooms, where the first
e# dimension is the building, the second the room number and the third is the
e# the floor number.
{ e# Run this block three times. At each stage it will find the index of the "*"
e# along the current dimension and leave the element at that index on the stack
e# for the next round...
_ e# Duplicate the current array.
{ e# Find the index of the first element where this block yields something
e# truthy...
s e# Flatten into a single string.
'*& e# Set intersection with "*".
}#
_) e# Duplicate the index and increment it, because the results should be 1-based.
@@= e# Pull up the array and the other copy of the index and select the
e# corresponding element.
}3*
;\ e# We've now got the building, room and floor index on the stack, as well as the
e# "*" character itself. We discard the character and swap the room and the floor
e# floor number. When the three indices are printed back-to-back at the end of
e# the program, that will yield the desired result.
JavaScript (ES6), 142 136 bytes
h=>h.split`
`.reverse(r=0).map((t,i,l)=>r?0:(f=i+1,b=1,l[o=0].slice(0,r=t.indexOf`*`+1).replace(/ /g,(_,s)=>o=++b&&s+2),r-=o))&&[b]+f+r
6 bytes saved thanks to @nderscore!
Explanation
h=>
h.split`
` // get each line of the input string
.reverse( // reverse the lines to make getting the ground floor easy
r=0) // initialise r to 0
.map((t,i,l)=> // for each line of the reversed input string
r?0:( // if the marked room has not been found yet:
f=i+1, // f = floor number
b=1, // b = building number, default to 1
l[o=0].slice(0, // get the substring of 0 to the marked room, default o to 0
r=t.indexOf`*`+1) // r = absolute index of room + 1 (or 0 if not found)
.replace(/ /g,(_,s)=> // count the spaces between buildings
o=++b&&s+2), // increment b, o = index of marked room's building
r-=o // make r relative to the room's building
)
)
&&[b]+f+r // output the result ([b] casts b to a string)
Test
var solution = h=>h.split`
`.reverse(r=0).map((t,i,l)=>r?0:(f=i+1,b=1,l[o=0].slice(0,r=t.indexOf`*`+1).replace(/ /g,(_,s)=>o=++b&&s+2),r-=o))&&[b]+f+r
<textarea id="input" rows="8" cols="60">#
# #
# # ##
# # ## ###
# # ## ### #####
# # ## ### ##*## ########
# # ## ### ##### ########</textarea><br />
<button onclick="result.textContent=solution(input.value)">Go</button>
<pre id="result"></pre>
Pyth, 34 bytes
LxKh/#\*b\*jkhM[//<hJ_.zyJd2xJKycK
Demonstration
This uses a golfing trick I've never used before: Assigning to a variable (K
) inside a function (y
) to save a partial result from that function.
Explanation:
LxKh/#\*b\*jkhM[//<hJ_.zyJd2xJKycK
L Define y(b): (b is a list of strigs)
/#\*b Filter b for strings containing '*'
h Take the first such string
K Store it in K
x \* And return the index of '*' in that string.
.z Take the input as a list of strings
_ Reverse it (bottom to top)
J Store in J
h Take the bottommost row
yJ Find y(J). This is the index in whichever
row of J has the * of the *. Also store
that row in K.
< Slice J up to that index.
/ d Count the number of spaces
/ 2 Divide by 2. This is the building number.
xJK Take the index in J of K. This is the floor.
cK Chop K on whitespace.
y Find the index in whatever element of K has
the * of the *. This is the room number.
This also overwrites K, but we don't care.
[ Gather the above into a list.
hM Convert 0-indexing to 1-indexing.
jk Concatenate. Print implicitly.