Building Demolition

11

1

Challenge

Write a full program/function to Demolish a given building at the rate 1 floor per second.

INPUT

Input is a building through STDIN(or whatever is called in your language) or through an ARGUMENT of a function. t=0 s

   |
  |#|
  {#}
 |# #|
|# # #|
|# # #|
|# # #|
TTTTTTT  

input consists of :

  • | marks start and end of a floor.
  • {,} marks the floor with explosives.
  • # is a window which is for decoration .
  • is space, which is everywhere inside the floors where # is not there.
  • T marks ground(cannot be demolished).
  • * marks the detonated floor.

Input rules :

  • building starts from top with one | and ends on ground(with no(T)=no (char used in ground floor)).
  • a window # is at every odd place inside every floor.
  • T marks the end of your input.
  • only one floor consists of explosives.
  • every floor is made of odd no. of chars.
  • as you ascend down the floors, the floors can either be of equal size of that of previous floor or can be 2 chars bigger.
  • Input can be taken as an array of chars or strings.

Output :

t=0.5 s

   |
  |#|
  ***
 |# #|
|# # #|
|# # #|
|# # #|
TTTTTTT  

t=1 s

   |
  |#|
 |# #|
|# # #|
|# # #|
|# # #|
TTTTTTT  

t=1.5 s

   |
  ***
 |# #|
|# # #|
|# # #|
|# # #|
TTTTTTT  

t=2 s

   |
 |# #|
|# # #|
|# # #|
|# # #|
TTTTTTT  

t=2.5 s

   *
 |# #|
|# # #|
|# # #|
|# # #|
TTTTTTT  

t=3 s

 |# #|
|# # #|
|# # #|
|# # #|
TTTTTTT  

t=3.5 s

 *****
|# # #|
|# # #|
|# # #|
TTTTTTT  

t=4 s

|# # #|
|# # #|
|# # #|
TTTTTTT  

t=4.5 s

*******
|# # #|
|# # #|
TTTTTTT  

t=6.5 s

*******
TTTTTTT  

t=7 s

TTTTTTT  

Output rules :

  • every floor ends with one newline character.
  • ground may/may not have a trailing newline.
  • output the building(or whats left of it) every 0.5 s.
  • Output is like animation which is modified every 0.5 s and is displayed.
    (Also feel free to post GIFs with your answer)

This is a Code-Golf so the code in shortest bytes wins!
last date of submission is exactly 5 days from now

(But you know what ? Winning is not everything, feel free to try this challenge in your favorite language, even after a winner has been declared :] ).

EDIT : I changed the way you take input (my bad actually).

Mukul Kumar

Posted 2016-11-25T05:23:32.107

Reputation: 2 585

What is answers are supposed to be posted after 1 hrs from now about? – Dennis – 2016-11-25T05:37:15.833

1 hr from the time of my post. so that I get at least 1 hr to rectify any question related doubts. – Mukul Kumar – 2016-11-25T05:41:13.873

8

I'm not sure if the community would be willing to enforce this kind of limitation. If you're not sure that your specification is solid, you can post the challenge draft in our sandbox to get feedback before posting it on main.

– Dennis – 2016-11-25T05:54:48.060

@dennis Hmm...removed – Mukul Kumar – 2016-11-25T05:57:23.320

Two questions: (1) May we assume there's no trailing whitespace on any floor? (2) May we assume there are no more lines of input after the ground? – H Walters – 2016-11-25T19:58:43.820

@walters No trailing whitespace = true(every floor ends with a newline). No lines of output after ground = true. – Mukul Kumar – 2016-11-26T02:55:37.977

Answers

4

Vim, 41 38 bytes

qw:sl 500m␍q/{␍qqjk^v$r*@wdd:-␍@w@qq@q

Here, ^ is used for a literal caret; ␍ is used for CTRL-M.

Explanation

qw:sl 500m␍q sleeps half a second, while recording the half second sleep as macro w. /{␍ moves to the floor with explosives. qq begins recording macro q, which will recursively call itself.

jk moves down and up; this generates an error if you're on the last line (ground); the error terminates the recursive macro. ^v$r* replaces everything from the first non-whitespace character to the end of the line with *'s. @w waits half a second, then dd deletes the current floor. :-␍ moves up a floor without terminating the macro if you're on the top line. @w then waits another half second, and @q calls the q macro (initially empty).

q@q stops recording the macro q, then calls it, triggering the recursion.

Animation

vim demolition

H Walters

Posted 2016-11-25T05:23:32.107

Reputation: 1 536

I was starving to see a gif!! – Mukul Kumar – 2016-11-26T02:57:14.957

I noticed nobody else put a gif in, but you said "feel free to", so for my post it was a must! Anyhow, my answer could be "golfed" further if rewritten in V. – H Walters – 2016-11-27T03:59:59.520

my answer could be "golfed" further...ain't that enough? :P – Mukul Kumar – 2016-11-30T08:11:42.100

4

JavaScript (ES6), 208 198 bytes

f=
(t,s=f=>setTimeout(f,500),v=t.value.split(/(\S.*\n)/),i=v.findIndex(s=>/}/.test(s)),c=_=>t.value=v.join``,d=_=>c(v.splice(--i,2),v[3]&&s(e,i?--i:++i)),e=_=>c(v[i]=v[i].replace(/./g,'*'),s(d)))=>s(e)
<textarea id=t rows=9>
   |
  |#|
  {#}
 |# #|
|# # #|
|# # #|
|# # #|
TTTTTTT
</textarea><input type=button value=Go! onclick=f(t)>

Neil

Posted 2016-11-25T05:23:32.107

Reputation: 95 035

2

Java 7, 589 477 476 bytes

import java.util.*;void x(List<String>b,int x)throws Exception{Thread.sleep(500);int i=0,l=b.size(),z=x;String w;for(;i<l;i++){System.out.println(w=b.get(i));if(w.contains("{"))x=i;}System.out.println();w=b.get(x);i=w.contains("*")?1:0;if(i>0)b.remove(x);else b.set(x,z<0?r(w,'{','}'):r(w,'|','|'));if(l>1)x(b,i>0&x>0?x-1:x);}String r(String s,char y,char z){int a,b;return s.substring(0,a=s.indexOf(y))+s.substring(a,b=s.lastIndexOf(z)+1).replaceAll(".","*")+s.substring(b);}

Ok, it's a mess/long, but this challenge has so many annoying things for Java.. Printing multi-line; Thread.sleep(500) which requires a throws Exception; replacing a substring between two delimiters with an equal amount of *; etc.
All this causes the program to be pretty big.. It can defintely be golfed some more, maybe even halved with a different approach, but at least there is an answer now. ;)

Ungolfed:

void x(List<String>b, int x) throws Exception{
  Thread.sleep(500);
  int i = 0,
      l = b.size(),
      z = x;
  String w;
  for(;i<l; i++){
    System.out.println(w=b.get(i));
    if(w.contains("{")){
      x = i;
    }
  }
  System.out.println();
  w = b.get(x);
  i = s.contains("*")
       ? 1
       : 0;
  if(i>0){
    b.remove(x);
  }
  else{
    b.set(x, z < 0
              ? r(s, '{', '}')
              : r(s, '|', '|'));
  }
  if(l>1){
    x(b, i > 0 & x > 0
          ? x-1
          : x);
  }
}

String r(String s, chary, char z){
    int a, b;
    return s.substring(0, a=s.indexOf(y)) + s.substring(a, b=s.lastIndexOf(z) + 1).replaceAll(".", "*") + s.substring(b);
}

Test code:

import java.util.*;

class M{
  void x(List<String>b,int x)throws Exception{Thread.sleep(500);int i=0,l=b.size(),z=x;String w;for(;i<l;i++){System.out.println(w=b.get(i));if(w.contains("{"))x=i;}System.out.println();w=b.get(x);i=w.contains("*")?1:0;if(i>0)b.remove(x);else b.set(x,z<0?r(w,'{','}'):r(w,'|','|'));if(l>1)x(b,i>0&x>0?x-1:x);}String r(String s,char y,char z){int a,b;return s.substring(0,a=s.indexOf(y))+s.substring(a,b=s.lastIndexOf(z)+1).replaceAll(".","*")+s.substring(b);}

  public static void main(String[] a){
    try{
        List<String> l = new ArrayList(){{
            add("   |   ");
            add("  |#|  ");
            add("  |#|  ");
            add(" {# #} ");
            add("|# # #|");
            add("|# # #|");
            add("|# # #|");
            add("TTTTTTT");
        }};
        new M().c(l, -1);
    }
    catch(Exception e){}
  }
}

Try it here. (On ideone it outputs at once and ignores the sleep..)

Kevin Cruijssen

Posted 2016-11-25T05:23:32.107

Reputation: 67 575

Catching the exception might save you a few bytes. Or maybe try{...}finally{return;}? – Neil – 2016-11-25T09:38:36.390

@Neil Thanks, but I've managed to merge both methods, so now I have a single throws Exception – Kevin Cruijssen – 2016-11-25T09:43:24.073

2

C, 314 287 281 271 bytes

s,e,t,i;f(char**b){char*p;do{system("CLS");i=0;do{while(!(p=b[i]))i++;if(!*b&&e==1)e=i;while(*p<33)putchar(*p++);if(!t)e=*p=='{'?i:e,s+=2;do{putchar(e==i&&t%2&&*p>16?'*':*p);}while(*p&&*p++>16);}while(*b[i++]-84);if(t++%2)b[e]=0,*b&&e>0?e--:e++;Sleep(500);}while(t<s-1);}

-10 after changing != to - and avoiding char literals when it is possible, as well as isspace (many thanks to H Walters). But ungolfed code remains unchanged.

s,e,t,i;f(char**b){char*p;do{system("CLS");i=0;do{while(!(p=b[i]))i++;if(!*b&&e==1)e=i;while(isspace(*p))putchar(*p++);if(!t)e=*p=='{'?i:e,s+=2;do{putchar(e==i&&t%2&&*p>0xF?'*':*p);}while(*p&&*p++>0xF);}while(*b[i++]!='T');if(t++%2)b[e]=0,*b&&e>0?e--:e++;Sleep(500);}while(t<s-1);}

-6 bytes after applying coma and deletion of {} after two if.

s,e,t,i;f(char**b){char*p;do{system("CLS");i=0;do{while(!(p=b[i]))i++;if(!*b&&e==1)e=i;while(isspace(*p))putchar(*p++);if(!t){s+=2;e=*p=='{'?i:e;}do{putchar(e==i&&t%2&&*p>0xF?'*':*p);}while(*p&&*p++>0xF);}while(*b[i++]!='T');if(t++%2){b[e]=0;e=*b&&e>0?e-1:e+1;}Sleep(500);}while(t<s-1);}

-26 bytes after little optimization, removal unnecessary parentheses, as well as change local variables to global (with auto 0 initialization) and b[0] by *b.

f(char**b){int s=0,e=0,t=0;char*p;do{system("CLS");int i=0;do{if(!t){s+=2;if(strchr(b[i],'}'))e=i;printf(b[i]);}else{while(!(p=b[i]))i++;if(!b[0]&&e==1)e=i;do{putchar((e==i&&t%2&&!isspace(*p))?'*':*p);}while(*p&&*p++!='\n');}}while(b[i++][0]!='T');if(t%2){b[e]=0;e=(b[0]&&e)?e-1:e+1;}t++;Sleep(500);}while(--s>1);}

Test code with ungolfed f:

#include <stdio.h>
#include <windows.h> // to use Sleep and system

s, e, t, i;
f(char**b)
{
    char*p;
    do{
        system("CLS");
        i = 0;
        do
        {
            while (!(p=b[i]))i++; // skip demolished floors
            if (!*b && e==1) e = i;
            while (isspace(*p)) putchar(*p++); // print spaces 
            if (!t){ s += 2; e = *p == '{' ? i : e; } // find a bomb and count steps at the first iteration
            do{
                putchar(e == i && t%2 &&*p>0xF ? '*' : *p); // print floor or * for next floor at odd step
            } while (*p && *p++ >0xF); // >0xF is instead of !='\n'
        } while (*b[i++] != 'T'); // until the ground
        if (t++ % 2)
        {
            b[e] = 0; // delete the demolished floor
            e = *b&&e>0 ? e-1 : e+1; // and determine next floor to be demolished
        }
        Sleep(500);
    } while (t<s-1);
}

int main(void)
{
    char * arr[] = { "   |\n",
                     "  |#|\n",
                     "  {#}\n",
                     " |# #|\n",
                     "|# # #|\n",
                     "|# # #|\n",
                     "|# # #|\n",
                     "TTTTTTT" };
    f(arr);
}

VolAnd

Posted 2016-11-25T05:23:32.107

Reputation: 296

1You can define s,e,t outside globally like this s,e,t; – Mukul Kumar – 2016-11-25T13:54:12.607

@MukulKumar you sure? – Mark Yisri – 2016-11-25T15:42:40.810

Yea sure go ahead and try it...,also include i with others. – Mukul Kumar – 2016-11-25T15:43:31.210

I will try some other optimization and use your suggestions as well – VolAnd – 2016-11-25T15:57:10.060

@MukulKumar Thanks for advice... -23 bytes – VolAnd – 2016-11-28T07:01:06.093

@voland int is not required in declaration and i=0 is also not required – Mukul Kumar – 2016-11-28T07:17:54.443

@MukulKumar So more -4 with deleted int, but i=0 is needed for each iteration in the do..while loop. Thanks! – VolAnd – 2016-11-28T07:40:39.197

e = *b&&e>0 ? e-1 : e+1; = *b&&e>0?e--:e++; saves 2 more – Mukul Kumar – 2016-11-28T08:37:46.207

Haven't looked too carefully, but you can golf this a bit more: Don't use!= (2 chars) in a boolean condition; use - instead; e.g., *b[i++]!='T' => *b[i++]-'T'. Only, 'T' is 3 characters, but 84 is 2 characters, so make this*b[i++]-84 (there are other char literals here whose ASCII code is <100; apply the same trick). – H Walters – 2016-11-29T16:52:45.623

@HWalters Thanks! That trick can really save some bytes – VolAnd – 2016-11-30T06:09:10.673

2

Haskell, 245 221 bytes

import System.Posix.Unistd
r=reverse
c#l|(i,j)<-span(<'!')l=i++(c<$j)
f[b]=[[b]]
f s|(h@(a:b),d:c)<-break(elem '{')s=(h++'*'#d:c):(h++c):f(init h++'{'#last h:c)|1<2=r<$>(f$r s)
mapM((usleep 500000>>).mapM putStrLn).init.f

Usage example:

mapM((usleep 500000>>).mapM putStrLn).init.f $ ["  |"," {#}"," |#|","|# #|","|# #|","TTTTT"]

How it works:

c#l|(i,j)<-span(<'!')l=i++(c<$j)    -- helper function that takes a char c and
                                    -- a string l and keeps the leading spaces
                                    -- of l and replaces the rest with c

                                    -- f takes a building (list of strings) and
                                    -- makes the sequence of collapsing buildings
                                    -- as a list of list of strings
f[b]=[[b]]                          -- base case. Stop when there's only a single
                                    -- floor left
f s                                 -- if the building has at least two floors
   |(h@(a:b),d:c)<-break(elem '{')s --   if there is at least one floor above the
                                    --   explosion
        =(h++'*'#d:c) :             --     return the current building with the
                                    --     floor to explode replaced by *
        (h++c) :                    --     followed by the current building with
                                    --     the exploded floor removed 
        f(init h++'{'#last h:c)     --     followed by a recursive call
                                    --     with the next to explode floor marked
                                    --     with '{'
   |1<2=r<$>(f$r s)                 --   if all top floors have exploded, reverse
                                    --   the left over floors, let them explode
                                    --   and reverse the floors of each building
                                    --   again.

                      f             -- let the building collapse
                 init               -- f comes with an additional building with
                                    -- a single floor of * only -> drop it
mapM(     )                         -- for every building
     (usleep 500000>>)              --   delay 0.5 sec
             mapM putStrLn          --   and print the floors

Note: there's also threadDelay from GHC.Conc instead of usleep from System.Posix.Unistd which is a little bit shorter, but it only works with the GHC compiler, so it wouldn't be a generic Haskell answer.

nimi

Posted 2016-11-25T05:23:32.107

Reputation: 34 639

1

Perl, 153 bytes

for(@a=<>;$a[$i]!~/{/;$i++){}for(;$a[0]!~/^T/;`sleep .5`){if($P=!$P){$a[$i]=~s/(\S.*\S|\S)/"*" x length($1)/e}else{splice(@a,$i,1);if($i){$i--}}print@a}

This uses GNU sleep command to wait for 500 milliseconds.

Ungolfed version

for(@a=<>;$a[$i]!~/{/;$i++){}
for(;$a[0]!~/^T/;`sleep .5`){
    if($P=!$P){
       $a[$i]=~s/(\S.*\S|\S)/"*" x length($1)/e
    } else { 
       splice(@a,$i,1);
       if($i){$i--}
    }
    print @a
 }

Adam

Posted 2016-11-25T05:23:32.107

Reputation: 591

1

PHP, 286 282 274 234 229 bytes

<?for($a=$argv,array_shift($a);!strstr($a[+$i++],"{"););while($a[0][0]!=T){$x=&$a[$i-=$i>0];$x=str_pad(substr($x,0,strspn($x," ")),strlen($x),"*");eval($p='echo join("\n",$a),"\n\n";usleep(5e5);');array_splice($a,$i,1);eval($p);}

takes input as list of strings from command line arguments (no newline character!)

save to file, run with php <filename> ' |' ' |#|' ' {#}' ' |# #|' '|# # #|' '|# # #|' '|# # #|' 'TTTTTTT'

breakdown

<?
for($a=$argv,array_shift($a);   // import input
    !strstr($a[+$i++],"{"););   // find explosives
while($a[0][0]!=T)              // loop while ground not reached:
{
    $x=&$a[$i-=$i>0];               // move up if possible, reference floor
    $x=str_pad(
        substr($x,0,strspn($x," ")  // keep leading spaces
    ),strlen($x),"*");              // replace rest with asterisks
                                    // print and wait
    eval($p='echo join("\n",$a),"\n\n";usleep(5e5);');
    array_splice($a,$i,1);          // remove current floor
    eval($p);                       // print and wait
}

Titus

Posted 2016-11-25T05:23:32.107

Reputation: 13 814