# Display Frames from .txt file

Given a .txt file with frames of ASCII art each separated by a \n (see this example if you are unclear) output a motion picture with frame with 1 frame per second.

Note that there is a trailing \n on the final frame.

Each frames dimensions will be:

• X<80
• Y<20

# The Rules

• The Previous frame must be cleared before the next is displayed, so just printing each frame onto the terminal isn't a valid answer.
• New You can grab the file name however you want, either from it being stored in a variable or from sys args.
• New The images must Loop indefinitely
• This is code golf: smallest program wins.

# Example

### Input

0   0
0   0
00000
0   0
0   0

00000
0
00000
0
00000

0   0
0 0
0
0
0


### Un-golfed

import curses, time

stdscr = curses.initscr()

while True:
y = 0
for i in range(len(Frames)):
stdscr.refresh()
y += 1
if Frames[i] == '':
y = 0
stdscr.clear()
time.sleep(1)

• In languages that don't really support file handling (like JavaScript), is it also OK to put the input in a variable? – ProgramFOX May 17 '14 at 15:46
• @ProgramFOX I guess you can open the file in a browser and use document.body.innerText – user12205 May 17 '14 at 18:19
• @ProgramFOX Make's it a little unfair, the file handling aspect adds many chars in most languages – Harry Beadle May 17 '14 at 23:41

## Mathematica, 41 bytes

Import@f~StringSplit~"\n\n"~ListAnimate~1


Expects the file name to be stored in variable f.

This is the first time Mathematica's precedence rules for @ and .~.~. are exactly the way I need them.

Btw, this snippet could go horribly wrong if the file extension is anything else than .txt (because Mathematica will try to guess how to do the import based on that), but luckily that file ending is part of the challenge specification.

## Bash, 82

IFS=
clear
for((;;)){
[ "$a" ]&&echo$a||(sleep 1;clear)
done<$1 }  Assumes the file name of the .txt file is provided as the first argument to the script. Note that a trailing empty line must be present at the end of the .txt file for this to work. Special thanks to @professorfish and @DigitalTrauma. • isn't $IFS blank by default? also, use for ((;;)){ ... } instead of while :;do ... done – user16402 May 18 '14 at 20:19
• @professorfish IFS by default is <space><tab><newline>. Need to set it to '' so that read can read multiple consecutive spaces, as in the last line of Y – user12205 May 18 '14 at 20:44
• A couple of small reductions: IFS= and [ "$a" ] instead of [ -n "$a" ] – Digital Trauma May 19 '14 at 19:45

# Ruby, 888656 55 characters

$<.read.split($/*2).cycle{|i|system'cls';$><<i;sleep 1}  This program assumes the file name is given as the first argument. Thanks a lot to Ventero for sharing great improvements! Un-golfed: $<.read.split($/*2).cycle{ |i| # read file, split by two newlines, and loop system 'cls' # clear screen$><<i   # print the current array item
sleep 1   # sleep one second
}


This program reads the file, splits it into chunks, and prints each chunk separately after clearing the screen. cls only works on Windows. A variant with clear is 57 characters.

• you can save a character or two, by using a line break instead of the first ; and omitting the parentheses when calling split. – Martin Ender May 17 '14 at 17:55
• That depends on how you configure your editor. :P I'm using almost exclusively Windows, but my Sublime is configured to use \n anyway. Also here on code golf no one will make you add another point to your score for each line break just because you are using Windows. ;) – Martin Ender May 17 '14 at 18:07
• $* is shorthand for ARGV, which would save two characters. In this case, you can save even more by using ARGF (or $<) though: a=$<.read.split"\n\n". a.size is also shorter than a.length. And since sleep returns its argument after returning, you can combine the last two statements in your loop into i+=sleep 1. – Ventero May 17 '14 at 23:45 • Actually, nevermind the last bit, you can completely eliminate i by using Array#cycle, which loops forever if no argument is given: a.cycle{|i|system"cls";$><<i;sleep 1}. And splitting at $/+$/ is another character shorter than "\n\n". – Ventero May 17 '14 at 23:47
• That also allows you to inline the definition of a: $<.read.split($/+$/).cycle{...} (Sorry about the triple comment, I always think of new improvements right after the comment edit period is over :) ) – Ventero May 17 '14 at 23:54 ## Dyalog APL (64) (Can't beat Mathematica this time. It seems to have a built-in for everything.) {⎕ML←3⋄{⎕SM←1 1,⍨⊂⊃⍵⊂⍨~⍵∊⎕TC⋄⎕DL 1}¨M⊂⍨~(4/1)⍷⎕TC∊⍨M←80 ¯1⎕MAP⍵}  This is a function that takes the filename as its argument. It assumes the file is in Windows (\r\n) format. Explanation: • ⎕ML←3: set migration level to 3 (allowing ⊂ to be used as APL2's split feature) • M←80 ¯1⎕MAP⍵: read the file given by the right argument as an ASCII file, and store the contents in M. • M⊂⍨~(4/1)⍷⎕TC∊⍨M: find all occurrences of four consecutive terminal control characters, and split M on those. This gives each frame. • {...}¨: for each of these... • ⊂⊃⍵⊂⍨~⍵∊⎕TC: split the argument (=one frame) on terminal control characters, and then turn the vector-of-vectors into a matrix (so it will display each line on a separate line, this is necessary because ⎕SM does not understand control characters.) • ⎕SM←1 1,⍨: then display it in the upper left of the ⎕SM window. • ⎕DL 1: and then wait for one second. • Ha, finally! And still my answer is not a lot shorter because the function names are just so damn long! :D – Martin Ender May 17 '14 at 18:30 • Someone needs to write a Mathematica preprocessor that maps every built in function to a Unicode character – Digital Trauma May 17 '14 at 20:54 # Awk, 53 BEGIN{RS=RS RS}{system("clear")}1;{system("sleep 1")}  New rules: # Awk, 74 BEGIN{RS=z}{a[NR]=$0}END{while(!system("sleep 1;clear"))print a[i++%NR+1]}

• This only loops once, but it can be shortened to BEGIN{RS=z}{system("sleep 1;clear")}1 ... In awk, "" is special as RS meaning multiline records. To support the new rule of looping indefinitely, I have this so far: BEGIN{RS=z}END{for(;!system("sleep 1;clear");)print a[i++%NR+1]}{a[NR]=$0} at 74 characters. gawk supports changing ARGV so you can do BEGIN{RS=z}{system("sleep 1;clear");ARGV[ARGC++]=ARGV[ARGC-1]}1 at 63 characters. – laindir May 19 '14 at 15:08 • @laindir: Thanks, I can't come up with anything better. – ephemient May 19 '14 at 16:23 ## Perl, 40 seek ARGV,0,!eof;sleep 1;system clear  run as perl -p00 frames.pl < animation.txt  (i.e. animation file is read through STDIN). 3 bytes for p00 were added to count. It's 2 characters shorter i.e. 38 on Windows because of cls instead of clear. Or, to be portable: seek ARGV,0,!eof;sleep 1;system$^O=~/Win/?cls:clear


Or, stretching rules a bit (and then 31+3=34):

seek ARGV,sleep(1)&reset,!eof


# Rebol, 74

forever[foreach s split to-string read f"^/^/"[call"clear"print s wait 1]]


Expects the filename to be stored in variable f. Below is an ungolfed example:

f: %ascii-art.txt

forever [
foreach s split to-string read f "^/^/" [
call "clear"
print s
wait 1
]
]


Java, 678 characters(when golfed)

Of course with GUI, since doing stuff in console sucks with Java, especially if you want to clear the screen ...

import java.awt.Font;
import java.io.File;
import java.util.Scanner;

import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;

public class G extends JFrame
{
static JTextArea b = new JTextArea();

G()
{
setSize(170, 370);

b.setFont(new Font(Font.MONOSPACED, 0, 50));
}

public static void main(final String[] args)
{
new G().setVisible(true);
new SwingWorker()
{
protected Void doInBackground()
{
for(;;)
{
try(Scanner s = new Scanner(new File(args[0])))
{
String l = null;
while(s.hasNextLine())
{
if(l == null  || (l = s.nextLine()).isEmpty())
{
b.setText(l == null ? (l = s.nextLine()) + '\n' : null);
}
else
b.setText(b.getText() + l + '\n');
}
}
catch(Exception i){}
}
}
}.execute();
}
}

• Just realized there were dimensions in the author's post, but I'm too lazy to change my code now. Won't win anyway :P – Leo Pflug May 19 '14 at 14:05

# Cobra - 163

class P
def main
while 1
print i
if i=="",.x
.x
def x
Console.clear


# Python 117

Assumes the file name is stored in variable f.

import time,os
while 1:
print i
if i=='':time.sleep(1);os.system('cls')


Note: replace 'cls' with 'clear' if on a unix based system, adding 2 chrs.

ctl+C to quit

• for i in F: s.addstr(y,0,i); ... if i=='': ... – user12205 May 18 '14 at 8:52
• Use open(f).read() instead of file.read(file(f)), shorter by 4 bytes. – nyuszika7h Jul 2 '14 at 18:02

## Groovy - 121 119 chars

Ported ProgramFOX's answer to Groovy 2.2.1. The "clear console" is weak.

edit: replaced recursive closure with simple while loop, which is shorter and no stack overflow

a=new File(args[0]).text.split "\n\n";i=0;p={println it};while(1){p a[i++%a.size()];Thread.sleep(1000);80.times{p ""}}


Ungolfed:

a = new File(args[0]).text.split "\n\n"
i = 0

p = { println it }

while(1) {
p a[i++%a.size()]
80.times{p ""}
}


# GNU sed, 32

1eclear
/^\$/{
esleep 1;clear
d
}


# Groovy, 81

This is a more groovy way:

new File(args[0]).text.split("\n\n").each{["cls"].execute();print it;sleep(1000)}


ungolfed

new File(args[0]).text.split("\n\n").each{
["cls"].execute()
print it
sleep(1000)
}

• The command "cls" doesn't work on my Mac. Also, the requirements suggest that the motion picture loops. – Michael Easter May 17 '14 at 22:02
• @Michael Easter cls is for Windows I think... try clear – user12205 May 18 '14 at 8:47

# C# 226

Why bother eh?

namespace System{class P{static void Main(){for(;;)foreach(var x in Text.RegularExpressions.Regex.Split(new IO.StreamReader("f.txt").ReadToEnd(),"\n\r\n")){Console.Clear();Console.WriteLine(x);Threading.Thread.Sleep(1000);}}}}


Un-golfed:

namespace System
{
class P
{
static void Main()
{
for(;;)
{
Console.Clear();
Console.WriteLine(x);
}
}
}
}


Or in LINQPAD (so C# can stay semi-competitive with uber shorthand langs :D)

for(;;)foreach(var x in Regex.Split(new StreamReader("f.txt").ReadToEnd(),"\n\r\n")){x.Dump();Thread.Sleep(1000);Util.ClearResults();}


I feel a bit dirty, but hey, this is code-golf.

# SmileBASIC, 74 bytes

F=LOAD(F)@L
IF" "*!CSRX>F[I]THEN WAIT 60CLS
?F[I];
I=(I+1)MOD LEN(F)GOTO@L


F should be the file name