Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

A simple one today. Write the shortest program that draws a "sawtooth alphabet" given a positive integer for the height. You must write the name of your programming language when you come to the letter it starts with.

For example, if your language is Python and the input is 1 the output should be:

ABCDEFGHIJKLMNOPythonQRSTUVWXYZ

If the input is 2 the output should be:

 B D F H J L N Python R T V X Z
A C E G I K M O      Q S U W Y

If the input is 4 the output should be:

   D     J     Python     V
  C E   I K   O      Q   U W
 B   F H   L N        R T   X Z
A     G     M          S     Y

Notes

  • A always starts at the bottom left.
  • Input can be via stdin or function call or similar. Output to stdout.
  • Input above 26 doesn't need to work.
  • No trailing spaces.
share|improve this question
9  
Are programming languages with one letter names allowed? (C, J, K, etc.) –  isaacg Jul 28 at 6:15
    
@isaacg Sure. I'd imagine it might be easier in them. –  Calvin's Hobbies Jul 28 at 6:16
1  
Can the input simply be expected to be stored in a variable? –  Martin Büttner Jul 28 at 10:17
    
@MartinBüttner Yes, that's fine. –  Calvin's Hobbies Jul 28 at 15:54
7  
Btw, this isn't a sawtooth wave, this is a triangle wave :P –  qwr Jul 29 at 1:04

22 Answers 22

C, 134

n,m,c,p;
main(r){
for(scanf("%d",&n),m=--n?n*2:1;n+r--;puts(""))
for(c=-1,p=1;c++<25;)
p+=(c-n-r)%m*((c-n+r)%m)?1:1-printf("%*c",p,c+65);
}

Compiles on gcc with a few warnings. Newlines aren't included in the character count.

122 characters if the input is already stored in n.

Thanks to user2992539, tolos and edc65 for improvements.

share|improve this answer
3  
You can use puts("") instead of printf("\n"). –  Somnium Jul 28 at 17:54
    
@user2992539 Thanks. –  grc Jul 28 at 21:32
2  
Save 4 characters with p-=(c-n+r)%m*((c-n-r)%m)?0:printf("%*c",p,c+65); instead of if((c-... –  tolos Jul 28 at 22:29
1  
Sorry for previous (deleted) comment.I was wrong. Playing with signs and abusing the fact that the first argument of main is 1 if there are no parameters: 134 n,m,c,p; main(r){ for(scanf("%d",&n),m=--n?n*2:1;n+r--;puts("")) for(c=-1,p=1;c++<25;) p+=(c-n-r)%m*((c-n+r)%m)?1:1-printf("%*c",p,c+65); } –  edc65 Jul 29 at 8:58

TI-BASIC - 148 bytes (raw text), 186 bytes (graphic)

In response to the OP, the wonderful TI-83 (and newer) comes with a size of 16 x 8 (just using the standard large text) or with a size of 94 x 62 pixels (which with small text is worth about 10 lines).

Now, this has a little problem (to which I would like clarification). The size impositions can't be "ignored" by the interpreter; in other words, if we were to try to set the sawtooth height at 20, it would give an error preventing the full execution of the code. I could write code that would, in an infinite environment, produce the correct output, except it wouldn't run on the machine.

With this being said, I present you the (running) versions of the programs. They all depend on the variable N being set to the desired height in lines before running:

  • Raw text approach

    :ClrHome
    :"ABCDEFGHIJKLMNOPQRSTI-BASICUVWXYZ"→Str1
    :8→R
    :For(C,1,16
    :If N=1
    :Then
    :0→F
    :Else
    :If R<2 or 10-R>N
    :1→F
    :If R>7
    :-1→F
    :End
    :If C≠20
    :Then
    :Output(R,C,sub(Str1,C,1
    :Else
    :Output(R,C,sub(Str1,C,8
    :C+7→C
    :End
    :R+F→R
    :End
    

    In order to make this work regardless of the terminal, change For(C,1,16 to For(C,1,33 and remove the upper bound checking (R<2 or). Here is the output with 5→N:

    enter image description here

  • Graphic approach (this may also need AxisOff for clarity)

    :ClrDraw
    :N*6→N
    :"ABCDEFGHIJKLMNOPQRSTI-BASICUVWXYZ"→Str1
    :57→R
    :For(C,1,56
    :If N=6
    :Then
    :0→F
    :Else
    :If R<7 or 64-R>N
    :6→F
    :If R>51
    :-6→F
    :End
    :If C≠20
    :Then
    :If C>50
    :Then
    :Text(R,C,sub(Str1,C-23,1
    :Else
    :Text(R,C,sub(Str1,C,1
    :End
    :Else
    :Text(R,C,sub(Str1,C,8
    :C+30→C
    :End
    :R+F→R
    :End
    

    This one works OK, with two minor quirks. The height is still a problem, although the width isn't. However, I didn't space the letters, so in some cases (when the letter starts to rise or decline from the sawtooth), the letters may be chopped off by their successors. To make it work regardless of the terminal, remove the upper bound check (R<7 or). Then follows the graph:

    enter image description here

share|improve this answer
    
Now I have to port this to my graphing calculator –  Outlaw Lemur Jul 29 at 14:22

if n holds the height:

C + escape codes: 81

x;main(y){for(y=n--;x<26;x++)printf("\033[%d;%dH%c",n?x/n&1?y++:y--:y,x+1,x+65);}

C: 110

x;char a[702]={[0 ...701]=32};main(y){for(y=--n;x<26;a[x*27-1]=10)a[27*(n?x/n&1?y++:y--:y)+x]=x+++65;puts(a);}
share|improve this answer
3  
I admit defeat. What on earth. :D –  Martin Büttner Jul 29 at 13:30
    
May I ask for compilation instructions? cc gives error "<bebe.c:1:17: error: ‘n’ undeclared (first use in this function)”. –  manatwork Jul 29 at 13:43
2  
well it is way worse than it looks. firstly the second one contains trailing spaces, secondly they both relies on that n is a global variable set to a number of your choice (as Martin has previously asked). –  bebe Jul 29 at 13:46
    
Oh, so I have to provide n in any way I can. Lol. Still impressed. –  manatwork Jul 29 at 14:10

Pure Bash (no coreutils), 181 bytes

m=$1
for l in A Bash {C..Z};{
((m))||s=++
((m>$1-2))&&s=--
for((m=$1==1?1:m,m$s,i=0;i<$1;i++));{
((i-m))&&a[i]+=${l//?/ }||a[i]+=$l
}
}
shopt -s extglob
printf %s\\n "${a[@]%%+( )}"

Output:

Piped to cat -E just to prove there are no trailing newlines.

$ ./sawtooth.sh 1 | cat -E
ABashCDEFGHIJKLMNOPQRSTUVWXYZ$
$ ./sawtooth.sh 5 | cat -E
       E       M       U$
      D F     L N     T V$
     C   G   K   O   S   W$
 Bash     H J     P R     X Z$
A          I       Q       Y$
$ 
share|improve this answer

JAVA (393)

As always a great language for golfing:

public class P{public static void main(String[]a){int h=Integer.valueOf(a[0]);String x="ABCDEFGHIJKLMNOPQRSTUVWXYZ";String[]l=new String[h];Arrays.fill(l,"");int i=h-1;int d=-1;for(char c:x.toCharArray()){for(int n=0;n<l.length;n++){String k=(n==i)?(c=='J')?"Java":c+"":(c=='J')?"    ":" ";l[n]+=k;}if(i==0&&d==-1)d=1;if(i==h-1&&d==1)d=-1;if(h>1)i+=d;}for(String s:l){System.out.println(s);}}}
share|improve this answer
2  
Unfortunately, you forgot the import for java.util.Arrays;. :-( –  Quincunx Jul 28 at 23:32
    
But you can imporve your code: eliminate String x="ABC...Z"; and replace the for(char c... loop header with for (char c=65;++c<91;){, I love chars in Java=) –  flawr Jul 29 at 14:01
    
Further you can replace c=='J' with c==74, saves two more bytes in total. –  flawr Jul 29 at 14:08
1  
I am sure you can do even better if you condense the if you use some XORs for those if statements, but here my improved version: (325) public class p{public static void main(String[]a){int h=Integer.valueOf(a[0]),i=h-1,d=-1,n;String[]l=new String[h];for(n=0;n<h;l[n++]="");for(char c=64;++c<91;){for(n=0;n<h;n++){String k=n==i?c==74?"Java":c+"":c==74?" ":" ";l[n]+=k;}if(i==0&d==-1)d=1;if(i==h-1&d==1)d=-1;i+=h>1?d:0;}for(String s:l)System.out.println(s);}} @Quincunx: no more need for import.util.Arrays; =) –  flawr Jul 29 at 14:44

JavaScript (ES6) 231 244

Edit Bug fix, some reordering and a different way of managing height==1
Moreover, changed to a function as this is allowed by OP, so no prompt() for input

No changes to the general algorithm that probably is NOT the best for this challenge

F=h=>{for(p=s=[i=z=b=t=''];++p<h;)i=1,z=b=' ',s[p]=t;for(p=--h,k=64;++k<91;)s[p]+=t+String.fromCharCode(k),k-74||(s=s.map((x,q)=>x+(p-q?'         ':'avascript'))),p-=i,p<0|p>h?(i=-i,p-=i+i,t=z,b=t+t):t+=b;console.log(s.join('\n'))}

Explained

F=h=>{
  // row in s for output must be initialized to ''. In the same step I make other initializations
  for(p=s=[i=z=b=t='']; ++p < h;) // initialize for height 1, all increment and spacing can be null
    i=1,z=b=' ',s[p]=t; // the for body is entered only if height > 1, initializing spacing and increment to the right values
  for(p=--h,k=64;++k<91;)
    s[p]+=t+String.fromCharCode(k),
    k-74||(s=s.map((x,q)=>x+(p-q?'         ':'avascript'))), // if 'J' modify each line of output adding the name or spacing
    p-=i,p<0|p>h?(i=-i,p-=i+i,t=z,b=t+t):t+=b; // index bouncing
  console.log(s.join('\n'))
}

Examples

1

ABCDEFGHIJavascriptKLMNOPQRSTUVWXYZ

3 going up

  C   G            K   O   S   W
 B D F H Javascript L N P R T V X Z
A   E   I            M   Q   U   Y

4 on top

   D     Javascript     P     V
  C E   I          K   O Q   U W
 B   F H            L N   R T   X Z
A     G              M     S     Y

7 going down

      G                    S
     F H                  R T
    E   I                Q   U
   D     Javascript     P     V
  C                K   O       W
 B                  L N         X Z
A                    M           Y
share|improve this answer

Ruby, 112 bytes

o="#{' '*29}
"*h
26.times{|i|o[(h-i%(h<2?1:2*h-2)-1).abs*30+i+(i>17?3:0)]=(i+65).chr}
puts o.gsub('R   ','Ruby')

Expects the input to be stored in h.

Let me know if this needs clarification.

share|improve this answer
    
Very minor but you can remove the space after %. –  Calvin's Hobbies Jul 28 at 16:09
    
@Calvin'sHobbies Ha, I didn't trust my syntax highlighting there :D. Will fix it later. –  Martin Büttner Jul 28 at 16:16

R (204)

f=function(x) {
  m=matrix(" ",x,26)
  i=x
  d=ifelse(x==1,0,-1)
  for (j in 1:26) {
    m[i,j]=LETTERS[j]
    if (!((i+d) %in% 1:x)) d=-d
    i=i+d
  }
  for (i in 1:x) cat(m[i,],"\n",sep="")
}

Result

> f(1)
ABCDEFGHIJKLMNOPQRSTUVWXYZ
> f(2)
 B D F H J L N P R T V X Z
A C E G I K M O Q S U W Y 
> f(3)
  C   G   K   O   S   W   
 B D F H J L N P R T V X Z
A   E   I   M   Q   U   Y 
> f(7)
      G           S       
     F H         R T      
    E   I       Q   U     
   D     J     P     V    
  C       K   O       W   
 B         L N         X Z
A           M           Y 
share|improve this answer
    
I see what you did there! Very smart... –  Kroltan Jul 28 at 23:57
1  
+1 Neat! You can get rid of the spaces around your for statements though (for(i in 1:x)cat(... for instance) or the one around %in%. –  plannapus Jul 29 at 11:11

Javascript - 248 224 235

z=~~prompt(),y="ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");y[9]="Javascript";for(w=[],v=0;v<z;v++)w[v]="\n";v--;for(i=0;i<26;i++){for(j=0;j<z;j++)w[j]+=j-v?i-9?" ":"          ":y[i];~~(i/(z-1))%2?v++:v--;}if(z==1)w=y;console.log(w.join(""))

Here is a link to the jsfiddle, where you can test it.
edit: Made a console log for a monospaced font and removed the commas if input==1.

share|improve this answer
    
Suggestions: 1: parseInt and Math.floor can be both changed with an integer coercing operation like |0 or ~~. 2: it's shorter to build the w array directly, without split. for(w=[],v=0;v<z;v++)w[v]="\n"; –  edc65 Jul 28 at 8:40
    
... and there is not an output statement (console.log or whatever you use in your fiddle, it's part of the char count) –  edc65 Jul 28 at 9:02
    
@edc65 Thank you for the tips. You were right I forgot the output here so i added an alert, but there is no mono spaced font so it looks pretty chaotic. –  izlin Jul 28 at 9:25
    
@izlin Instead of (i==9?" ":" ") you could use (i^9?" ":" "), which saves a character. –  AcidShout Jul 28 at 12:11
1  
HELP! can anyone explain? (Why is there twice <code>v=0</code>?) –  flawr Jul 28 at 14:32

Bash (213) (223)

read i
p=0
d=1
printf '\n%.0s' `seq $i`
for l in {A..Z}
do (($p==$i-1))&&((p=$p*-1))
(($i==1))&&p=0
(($p!=0))&&echo -en "\033[s\033[${p#-}A"
[[ "$l" == "B" ]]&&l="Bash"
echo -en $l"\033[s\033[${p#-}B"
((p++))
done

Minor tweaks and we're down to 213.

The original one had a minor bug. Tested and confirmed to work on bash version 4.2.37.

Thanks to @manatwork for pointing out the bug and some tips.

share|improve this answer
    
I edited your post by adding syntax highlighting to it, but now I see that it wrongly highlighted a part of your code as a comment, so I rolled it back. I just said this in case you were wondering why I rolled it back :) –  ProgramFOX Jul 28 at 12:30
    
@ProgramFOX That's alright. Thanks anyhow! –  Okw Jul 28 at 14:20
    
I think there is minor bug somewhere, as the output is slowly descending. (At least in Bash 4.3.) Some minor improvements to reduce the size to 194 characters: omit the sigil in arithmetic evaluation, do not try to double-quote inside double-quoted string: pastebin.com/zKa3zdwR –  manatwork Jul 28 at 15:28
    
Can you use newlines instead of some of the ; just to make it a tiny bit more readable? It won't affect your golf score –  DigitalTrauma Jul 28 at 19:43

C, 214 169 bytes, no trailing spaces

Thank to @edc65 and @tolos for their helpful suggestions.

#define C ((c-i+n-65)%z&&(c+i+n-67)%z)
n,i,m,c,z;main(){scanf("%d",&n);z=n<2?1:2*n-2;for(;i++<n;){for(m=c=64;c++<90;)m=C?m:c;for(c=64;c++<m;)putchar(C?32:c);puts("");}}
share|improve this answer
3  
It's a lost battle, but I persist: #include <stdio.h> is not needed in many cases, be it gcc or any other compiler. It's standard and valid C anyway. –  edc65 Jul 28 at 9:07
2  
@edc65: Depends on what you consider "valid C". It is AFAIK valid K&R C, but ANSI/ISO C demands that variadic functions (which include scanf and printf) are given prototypes, otherwise you'll get undefined behaviour. #include <stdio.h> is, of course, the shortest way to give a prototype to both scanf and printf. –  celtschk Jul 28 at 9:34
    
@celtschk valid K&R is enough for me in code golf. And 'in many cases' (when just using puts for instance) is valid C89. What I want stress out is that is not a strange behaviour of gcc. (Thks for the note about variadic functions, anyway) –  edc65 Jul 28 at 10:15
1  
Globals are type int and initialized to zero. Might as well drop int declaration for main if you aren't returning anything. Can drop extra parens, replace ' ' with 32 and if(!C)m=c with a ternarny statement, and as I just learned (above) replace printf("\n") with puts("") for 18 characters: n,i,m,c,z;main(){;scanf("%d",&n);z=n<2?1:2*n-2;for(;i<n;i++){for(m=c=65;c<91;c+‌​+)m=C?m:c;for(c=65;c<=m;c++)printf("%c",C?32:c);puts("");}} –  tolos Jul 28 at 22:51

J : 75 bytes

NB. without IO |:26([:u:65+i.@[)`(($(,|.@}.@}:)@i.)<"1@,.i.@[)`(' '$~,~)}5
2(1!:2)~|.26([:u:65+i.@[)`(($(,|.@}.@}:)@i.)<"1@,.i.@[)`(' '$~,~)}".1!:1[1

Using the wonderful Amend conjunction. As usual the IO is ugly and clunky, not going into details there. The core solution takes 3 gerunds (a sort of noun-ified verb (aka. function)):

  • a) generating the alphabet
  • b) generating the indices
  • c) generating the matrix to make amends to

    x (abc}) y

a) is a pretty trivial lookup in the ascii table

c) is even more trivial

b) is the interesting one. The morale is that the horizontal indices are supposed to be starting from 0 going to y-1 and back down, repeating this 26 times. Eg. for y == 4:

0 1 2 3 2 1 0 1 2 3 2 1 ...

Implementing this gives for b):

($(,|.@}.@}:)@i.) <"1@,. i.@[)       NB. is equivalent too
(tine0 tine1 tine2)                  NB. a fork with tines defined as
tine0 =: 
  hook0 =: hook0_0 hook0_1           NB. a dyadic hook: x (g h) y -: x g h y
     hook0_0 =: $                    NB. reshape
     hook0_1 =: (hook1_0 hook1_1)@i. NB. do hook1 after making 0-y
       hook1_0=: ,                   NB. append to self
       hook1_1=: |.@}.@}:            NB. rotated version of y after beheading and curtailing
tine2 =: i.@[                  NB. generate 0-x
tine1 =: <"1@,.                NB. glue together coordinates.

And oh yea, handy fact: J's name is ... "J".

share|improve this answer
    
Is it worth to use amend? It seems easier to me to say something like 3 :'|:(26$1+(i.1=y),}:|i:<:y)|.@{."+u:65+i.26' The ugly part in that solution is the 8 characters just to special case height 1, but this can probably be shortened a bit. –  Zsbán Ambrus Jul 30 at 9:40
    
Thanks for the suggestion! Yours is indeed far shorter, and amend is probably overkill. Since it's so different, maybe you'd want to post it as a solution yourself? –  jpjacobs Jul 30 at 15:34
    
The spec says "no trailing spaces" and my solution does print trailing spaces. –  Zsbán Ambrus Jul 30 at 20:20

Haskell – 432 Bytes (unfortunately...)

This turned out to be much harder than I expected to accomplish purely, hence the hefty byte count. I am sure I (or someone) could do better, but I've spent too much time on this as it is. The golfed version is as follows:

import Data.Matrix
import Data.Vector(toList)
r=repeat
s h=y h$l(take 26(case h of 1->r 1;_->concat$r$[h,h-1..1]++[2..h-1]))['A'..'Z']$matrix h 32(const ' ')<|>matrix h 1(const '\n')
l _[]m=m
l(x:i)(r:e)m=l i e$u m(let z=26-length i in if z<9 then z else z+6)x r
l _ _ m=m
u m c r h=case h of 'H'->t c r"Haskell"m;_->setElem h(r,c)m
t _ _[]m=m
t c r(x:i)m=t(c+1)r i$setElem x(r,c)m
y h m=concat[toList$getRow x m|x<-[1..h]]

To run, load the code into ghci and execute putStr $ s Int where Int is your desired height. You could also add

import System.Environment
main :: IO ()
main = fmap (s . read . head) getArgs >>= putStr

under the imports in a text file, compile it with ghc, and pass the height as a command line argument. Ungolfed version:

import System.Environment
import Data.Matrix
import Data.Vector (toList)

main :: IO ()
main = fmap (sawtooth . read . head) getArgs >>= putStr

type M = Matrix Char

sawtooth :: Int -> String
sawtooth height = let mat     = matrix height 32 (const ' ') <|> matrix height 1 (const '\n')
                      numbers = take 26 (case height of 1 -> repeat 1
                                                        _ -> concat $ repeat $ [height,height-1..1]++[2..height-1])
                      chars   = ['A'..'Z']
                  in toString height $ makeMatrix numbers chars mat

makeMatrix :: [Int] -> String -> M -> M
makeMatrix []     []     mat = mat
makeMatrix (x:xs) (s:ss) mat = makeMatrix xs ss $ updateMatrix
                                                    mat (let z = 26 - length xs in if z < 9 then z else z + 6) x s
makeMatrix _      _      mat = mat

updateMatrix :: M -> Int -> Int -> Char -> M
updateMatrix mat col row char = case char of 'H' -> insertHaskell col row "Haskell" mat
                                             _   -> setElem char (row, col) mat

insertHaskell :: Int -> Int -> String -> M -> M
insertHaskell _   _   []     mat = mat
insertHaskell col row (x:xs) mat = insertHaskell (col+1) row xs $ setElem x (row, col) mat

toString ::Int -> M -> String
toString height mat = concat [ toList $ getRow x mat | x <- [1..height] ]
share|improve this answer

C#/LINQ:

using System;
using System.Linq;

namespace SawtoothAlphabet
{
    class Program
    {
        static void Main(string[] args)
        {
            int N = Int32.Parse(args[0]);   // eg 4
            Console.WriteLine(
                String.Join(Environment.NewLine, Enumerable.Range(0, N).Select(line =>
                    String.Concat(Enumerable.Range(0, 26).Select(i =>
                        line == Math.Abs(i % (2 * (N - 1)) - (N - 1))
                            ? (i == 2) ? "C#" : Char.ConvertFromUtf32(i + 'A')
                            : (i == 2) ? "  " : " ")
            ).TrimEnd())));
        }
    }
}

Brief explanation: Enumerable.Range(0, N).Select(...) causes a string to be generated for each line which is eventually concatenated into a single string with String.Join(Environment.NewLine, ...). For each line we cycle through all 26 characters with Enumerable.Range(0, 26).Select(...), the test at the start of the lambda expression determines whether to generate a character or space while the i==2 checks for "C" and converts it to either "C#" or two spaces depending on the line. The String.Concat(...) converts the resulting IEnumerable<char> for each line into a string before passing it to TrimEnd(...) to cleanly strip away any trailing whitespace.

share|improve this answer

Javascript (204185)

h=m=4;d=h>1?-1:0;o=[];for(a=0;a<35;a++){for(r=h;r;r--)o[r]=(o[r]||"")+(r==m?"ABCDEFGHIJavascriptKLMNOPQRSTUVWXYZ"[a]:" ");if(a<9||a>17){m+=d;if(m<2||m==h)d=-d}}console.log(o.join("\n"))
share|improve this answer
    
I like it even if I don't understand it full. But anyway you can cut 9 chars removing substr and using direct index .substr(a,1) => [a] –  edc65 Jul 30 at 8:30

PHP (216) (205)

New version:

$b=array_fill(65,26,' ');$b[80]='   ';$b=array_fill(0,$i,$b);for($j=--$i,$x=64;++$x<91;$i||$j=0){$b[$j][$x]=chr($x);$x==80&&$b[$j][$x]='PHP';$j+=($d=$j<($d?$i:1))*2-1;}echo join("\n",array_map('join',$b));

Old version:

$b=array_fill(0,$i,array_fill(0,28,' '));for($j=--$i,$x=-1;++$x<28;$i||$j=0){$q=&$b[$j];$q[$x]=chr($x-($x&16)/8+65);$x==15&&($q[++$x]='H')*$q[++$x]='P';$j+=($d=$j<($d?$i:1))*2-1;}echo join("\n",array_map('join',$b));

expects the variable $i to be the height.

share|improve this answer

MetaPost (207)

numeric h,d,y;h=5;d=-1;y=1;u=5mm;pair p;string s;for x=1upto26:p:=(x,y)*u;s:=char(x+64);if x=13:s:="MetaPost";elseif x>13:p:=(x+2,y)*u;fi;label.rt(s,p);if(y=h)or(y=1):d:=d*-1;fi;if h=1:d:=0;fi;y:=y+d;endfor;

You can try it here.

share|improve this answer

C: 142 139 characters

Dreadfully long, I expect to be able to shorten it a bit:

char a[26][27],i,j,p,d;main(n){for(scanf("%d",&n);i<26;d^=!p^p+2>n,p+=d-(d^n>1),i++)for(j=n;j--;a[j][i]=p^j?32:i+65);while(n)puts(a[--n]);}

Slightly more readable:

char a[26][27], i, j, p, d;
main(n) {
    for (
        scanf("%d", &n);
        i < 26;
        d ^= !p ^ p + 2 > n,
        p += d - (d ^ n > 1),
        i++
    )
        for (
            j = n;
            j--;
            a[j][i] = p ^ j
                ? 32
                : i + 65
        );

    while (n)
        puts(a[--n]);
}

Edit: I missed the "no trailing spaces"-rule, but I will be back.

share|improve this answer

Scala, 246 bytes

def f(h:Int)={val a=Seq.fill(h)(Array.fill(32)(' '));var(r,x,d)=(h-1,0,if(h==1)0 else-1);def p(c:Char){a(r)(x)=c;x+=1};for(c<-'A'to'Z'){p(c);if(c==83)"cala"foreach p;r+=d;if(r==0|r==h-1)d*= -1};for(z<-a)println(new String(z)replaceAll(" +$",""))}

reformatted and commented:

def f(h: Int) = {
  val a = Seq.fill(h)(Array.fill(32)(' '));
  // r - row; x - x coordinate, column; d - direction
  var (r, x, d) = (h - 1, 0, if(h==1) 0 else -1); 
  def p(c: Char) { // p for "put the character"
    a(r)(x) = c;
    x += 1
  };
  for(c <- 'A' to 'Z') { 
    p(c);
    if(c == 83)      // 83 == 'S'
      "cala" foreach p;
    r += d;
    if(r == 0 | r == h - 1)     // | is shorter than || 
      d *= -1
  };
  for(z <- a)
    println(new String(z) replaceAll (" +$", ""))  // trimming trailing whitespace
}

Results:

scala> f(4)
   D     J     P         V
  C E   I K   O Q       U W
 B   F H   L N   R     T   X Z
A     G     M     Scala     Y

scala> f(5)
    E       M           U
   D F     L N         T V
  C   G   K   O   Scala   W
 B     H J     P R         X Z
A       I       Q           Y

scala> f(1)
ABCDEFGHIJKLMNOPQRScalaTUVWXYZ
share|improve this answer

Python - 137

Input to be stored in i. e.g. i=8

l=[""]*h;k=j=0;y=h-1;exec'l[y]+=" "*(j-len(l[y]))+chr(k+65)+"ython"*(k==15);j=len(l[y]);y-=1^k/(h-(h>2))%2*-2;k+=1;'*26;print"\n".join(l)
share|improve this answer

Racket

Here's a clean functional version: suggestions to shorten it welcome.

(define (sawtooth n)
  (define (ST i d m lns)
    (if (null? m) 
        lns
        (let* ([v (first m)]
               [spc (make-string (string-length v) #\space)]
               [I (+ i d)])
          (ST I
              (if (or (zero? I) (= (sub1 n) I)) (* d -1) d)
              (rest m)
              (for/list ([ln lns] [j n])
                       (~a ln (if (= i j) v spc)))))))
  (displayln
   (string-join 
    (ST (sub1 n)
        (if (= n 1) 0 -1) 
        (string-split "A B C D E F G H I J K L M N O P Q Racket S T U V W X Y Z")
        (make-list n "\n")))))

Output

> (sawtooth 1)
ABCDEFGHIJKLMNOPQRacketSTUVWXYZ

> (sawtooth 2)
 B D F H J L N P Racket T V X Z 
A C E G I K M O Q      S U W Y 

> (sawtooth 8)
       H                  V     
      G I                U W    
     F   J              T   X   
    E     K            S     Y  
   D       L     Racket       Z 
  C         M   Q               
 B           N P                
A             O  
share|improve this answer

Perl 119

$s.=/26/?++$r&&$/:$m-1&&$r-abs$_%(2*$m-2)+1-$m?$"x(1+3*/15/):/15/?Perl:(A..Z)[$_]for(0..26)x($m=<>);print$s=~s/\s+$//rg

This program takes input from STDIN and prints the result to STDOUT.

And bonus - a version that is against the rules as it prints trailing spaces, but adds some interaction:

#!/usr/bin/perl -p
$r=0;$_=join'',map{/26/?++$r&&$/:$m-1&&$r-abs$_%(2*$m-2)+1-$m?$"x(1+3*/15/):/15/?Perl:(A..Z)[$_]}(0..26)x($m=$_)

...and some tests below:

1
ABCDEFGHIJKLMNOPerlQRSTUVWXYZ
2
 B D F H J L N Perl R T V X Z
A C E G I K M O    Q S U W Y
4
   D     J     Perl     V
  C E   I K   O    Q   U W
 B   F H   L N      R T   X Z
A     G     M        S     Y
6
     F         Perl         Z
    E G       O    Q       Y
   D   H     N      R     X
  C     I   M        S   W
 B       J L          T V
A         K            U
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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