11
\$\begingroup\$

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).

\$\endgroup\$
  • \$\begingroup\$ What is answers are supposed to be posted after 1 hrs from now about? \$\endgroup\$ – Dennis Nov 25 '16 at 5:37
  • \$\begingroup\$ 1 hr from the time of my post. so that I get at least 1 hr to rectify any question related doubts. \$\endgroup\$ – Mukul Kumar Nov 25 '16 at 5:41
  • 7
    \$\begingroup\$ 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. \$\endgroup\$ – Dennis Nov 25 '16 at 5:54
  • \$\begingroup\$ @dennis Hmm...removed \$\endgroup\$ – Mukul Kumar Nov 25 '16 at 5:57
  • \$\begingroup\$ 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? \$\endgroup\$ – H Walters Nov 25 '16 at 19:58
3
\$\begingroup\$

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

\$\endgroup\$
  • \$\begingroup\$ I was starving to see a gif!! \$\endgroup\$ – Mukul Kumar Nov 26 '16 at 2:57
  • \$\begingroup\$ 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. \$\endgroup\$ – H Walters Nov 27 '16 at 3:59
  • \$\begingroup\$ my answer could be "golfed" further...ain't that enough? :P \$\endgroup\$ – Mukul Kumar Nov 30 '16 at 8:11
4
\$\begingroup\$

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)>

\$\endgroup\$
2
\$\begingroup\$

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..)

\$\endgroup\$
  • \$\begingroup\$ Catching the exception might save you a few bytes. Or maybe try{...}finally{return;}? \$\endgroup\$ – Neil Nov 25 '16 at 9:38
  • \$\begingroup\$ @Neil Thanks, but I've managed to merge both methods, so now I have a single throws Exception \$\endgroup\$ – Kevin Cruijssen Nov 25 '16 at 9:43
2
\$\begingroup\$

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.

\$\endgroup\$
2
\$\begingroup\$

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);
}
\$\endgroup\$
  • 1
    \$\begingroup\$ You can define s,e,t outside globally like this s,e,t; \$\endgroup\$ – Mukul Kumar Nov 25 '16 at 13:54
  • \$\begingroup\$ @MukulKumar you sure? \$\endgroup\$ – Mark Yisri Nov 25 '16 at 15:42
  • \$\begingroup\$ Yea sure go ahead and try it...,also include i with others. \$\endgroup\$ – Mukul Kumar Nov 25 '16 at 15:43
  • \$\begingroup\$ I will try some other optimization and use your suggestions as well \$\endgroup\$ – VolAnd Nov 25 '16 at 15:57
  • \$\begingroup\$ @MukulKumar Thanks for advice... -23 bytes \$\endgroup\$ – VolAnd Nov 28 '16 at 7:01
1
\$\begingroup\$

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
 }
\$\endgroup\$
1
\$\begingroup\$

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
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.