Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
Challenge
The shortest program by character count that accepts standard input of the form X-Y R, with the following guarantees:
R is a non-negative decimal number less than or equal to 8
X and Y are non-negative angles given in decimal as multiples of 45° (0, 45, 90, 135, etc.)
X is less than Y
Y is not 360 if X is 0
And produces on standard output an ASCII "arc" from the starting angle X to the ending angle Y of radius R, where:
The vertex of the arc is represented by o
Angles of 0 and 180 are represented by -
Angles of 45 and 225 are represented by /
Angles of 90 and 270 are represented by |
Angles of 135 and 315 are represented by \
The polygonal area enclosed by the two lines is filled with a non-whitespace character.
The program is not required to produce meaningful output if given invalid input. Solutions in any language are allowed, except of course a language written specifically for this challenge, or one that makes unfair use of an external utility. Extraneous horizontal and vertical whitespace is allowed in the output provided that the format of the output remains correct.
Happy golfing!
Numerous Examples
Input:
0-45 8
Output:
/
/x
/xx
/xxx
/xxxx
/xxxxx
/xxxxxx
/xxxxxxx
o--------
Input:
0-135 4
Output:
\xxxxxxxx
\xxxxxxx
\xxxxxx
\xxxxx
o----
Input:
180-360 2
Output:
--o--
xxxxx
xxxxx
Input:
45-90 0
Output:
o
Input:
0-315 2
Output:
xxxxx
xxxxx
xxo--
xxx\
xxxx\
Perl, 235 211 225 211 207 196 179 177 175 168 160 156 146 chars
<>=~/-\d+/;for$y(#a=-$'..$'){print+(map$_|$y?!($t=8*($y>0)+atan2(-$y,$_)/atan2 1,1)&-$&/45==8|$t>=$`/45&$t<=-$&/45?qw(- / | \\)[$t%4]:$":o,#a),$/}
Perl using say feature, 161 149 139 chars
$ echo -n '<>=~/-\d+/;for$y(#a=-$'"'"'..$'"'"'){say map$_|$y?!($t=8*($y>0)+atan2(-$y,$_)/atan2 1,1)&-$&/45==8|$t>=$`/45&$t<=-$&/45?qw(- / | \\)[$t%4]:$":o,#a}' | wc -c
139
$ perl -E '<>=~/-\d+/;for$y(#a=-$'"'"'..$'"'"'){say map$_|$y?!($t=8*($y>0)+atan2(-$y,$_)/atan2 1,1)&-$&/45==8|$t>=$`/45&$t<=-$&/45?qw(- / | \\)[$t%4]:$":o,#a}'
Perl without trailing newline, 153 143 chars
<>=~/-\d+/;for$y(#a=-$'..$'){print$/,map$_|$y?!($t=8*($y>0)+atan2(-$y,$_)/atan2 1,1)&-$&/45==8|$t>=$`/45&$t<=-$&/45?qw(- / | \\)[$t%4]:$":o,#a}
Original version commented:
$_=<>;m/(\d+)-(\d+) (\d+)/;$e=$1/45;$f=$2/45; # parse angles and radius, angles are 0-8
for$y(-$3..$3){ # loop for each row and col
for$x(-$3..$3){
$t=atan2(-$y,$x)/atan2 1,1; # angle of this point
$t+=8if($t<0); # normalize negative angles
#w=split//,"-/|\\"x2; # array of ASCII symbols for enclosing lines
$s.=!$x&&!$y?"o":$t==$e||$t==$f?$w[$t]:$t>$e&&$t<$f?"x":$";
# if it's origin -> "o", if it's enclosing line, get symbol from array
# if it's between enclosing angles "x", otherwise space
}
$s.=$/;
}
print$s;
EDIT 1: Inlined sub, relational and equality operators return 0 or 1.
EDIT 2: Added version with comments.
EDIT 3: Fixed enclosing line at 360º. Char count increased significantly.
EDIT 4: Added a shorter version, bending the rules.
EDIT 5: Smarter fix for the 360º enclosing line. Also, use a number as fill. Both things were obvious. Meh, I should sleep more :/
EDIT 6: Removed unneeded m from match operator. Removed some semicolons.
EDIT 7: Smarter regexp. Under 200 chars!
EDIT 8: Lots of small improvements:
Inner for loop -> map (1 char)
symbol array from split string -> qw (3 chars)
inlined symbol array (6 chars, together with the previous improvement 9 chars!)
Logical or -> bitwise or (1 char)
Regexp improvement (1 char)
Use arithmethic for testing negative angles, inspired by Jacob's answer (5 chars)
EDIT 9: A little reordering in the conditional operators saves 2 chars.
EDIT 10: Use barewords for characters.
EDIT 11: Moved print inside of loop, inspired by Lowjacker's answer.
EDIT 12: Added version using say.
EDIT 13: Reuse angles characters for fill character, as Gwell's answer does. Output isn't as nice as Gwell's though, that would require 5 additional chars :) Also, .. operator doen't need parentheses.
EDIT 14: Apply regex directly to <>. Assign range operator to a variable, as per Adrian's suggestion to bta's answer. Add version without the final newline. Updated say version.
EDIT 15: More inlining. map{block}#a -> map expr,#a.
Lua, 259 characters
Slightly abuses the non-whitespace character clause to produce a dazzling display and more importantly save strokes.
m=math i=io.read():gmatch("%d+")a=i()/45 b=i()/45 r=i()for y=r,-r,-1 do for x=-r,r do c=m.atan2(y,x)/m.pi*4 c=c<0 and c+8 or c k=1+m.modf(c+.5)io.write(x==0 and y==0 and'o'or c>=a and c<=b and('-/|\\-/|\\-'):sub(k,k)or c==0 and b==8 and'-'or' ')end print()end
Input: 45-360 4
\\\|||///
\\\|||//
\\\\|//
--\\|/
----o----
--//|\\--
////|\\\\
///|||\\\
///|||\\\
Able to handle odd angles
Input: 15-75 8
|/////
|//////
|//////
|//////
///////
|//////-
////---
//-
o
MATLAB, 188 chars :)
input '';[w x r]=strread(ans,'%d-%d%d');l='-/|\-/|\-';[X Y]=meshgrid(-r:r);T=atan2(-Y,X)/pi*180;T=T+(T<=0)*360;T(T>w&T<x)=-42;T(T==w)=-l(1+w/45);T(T==x)=-l(1+x/45);T(r+1,r+1)=-'o';char(-T)
Commented code:
%%# Get the string variable (enclose in quotes, e.g. '45-315 4')
input ''
%%# Extract angles and length
[w x r]=strread(ans,'%d-%d%d');
%%# Store characters
l='-/|\-/|\-';
%%# Create the grid
[X Y]=meshgrid(-r:r);
%%# Compute the angles in degrees
T=atan2(-Y,X)/pi*180;
%%# Get all the angles
T=T+(T<=0)*360;
%# Negative numbers indicate valid characters
%%# Add the characters
T(T>w&T<x)=-42;
T(T==w)=-l(1+w/45);
T(T==x)=-l(1+x/45);
%%# Add the origin
T(r+1,r+1)=-'o';
%%# Display
char(-T)
Mathematica 100 Chars
Out of competition because graphics are too perfect :)
f[x_-y_ z_]:=Graphics#Table[
{EdgeForm#Red,Disk[{0,0},r,{x °,y °}],{r,z,1,-1}]
SetAttributes[f,HoldAll]
Invoke with
f[30-70 5]
Result
alt text http://a.imageshack.us/img80/4294/angulosgolf.png
alt text http://a.imageshack.us/img59/7892/angulos2.png
Note
The
SetAttributes[f, HoldAll];
is needed because the input
f[a-b c]
is otherwise interpreted as
f[(a-b*c)]
GNU BC, 339 chars
Gnu bc because of read(), else and logical operators.
scale=A
a=read()/45
b=read()/45
c=read()
for(y=c;y>=-c;y--){for(x=-c;x<=c;x++){if(x==0)if(y<0)t=-2else t=2else if(x>0)t=a(y/x)/a(1)else if(y<0)t=a(y/x)/a(1)-4else t=a(y/x)/a(1)+4
if(y<0)t+=8
if(x||y)if(t==a||t==b||t==b-8){scale=0;u=(t%4);scale=A;if(u==0)"-";if(u==1)"/";if(u==2)"|";if(u==3)"\"}else if(t>a&&t<b)"x"else" "else"o"};"
"}
quit
MATLAB 7.8.0 (R2009a) - 168 163 162 characters
Starting from Jacob's answer and inspired by gwell's use of any non-whitespace character to fill the arc, I managed the following solution:
[w x r]=strread(input('','s'),'%d-%d%d');
l='o -/|\-/|\-';
X=meshgrid(-r:r);
T=atan2(-X',X)*180/pi;
T=T+(T<=-~w)*360;
T(T>x|T<w)=-1;
T(r+1,r+1)=-90;
disp(l(fix(3+T/45)))
And some test output:
>> arc
0-135 4
\||||////
\|||///-
\||//--
\|/---
o----
I could reduce it further to 156 characters by removing the call to disp, but this would add an extra ans = preceding the output (which might violate the output formatting rules).
Even still, I feel like there are some ways to reduce this further. ;)
Ruby, 292 276 186 chars
x,y,r=gets.scan(/\d+/).map{|z|z.to_i};s=(-r..r);s.each{|a|s.each{|b|g=Math::atan2(-a,b)/Math::PI*180/1%360;print a|b==0?'o':g==x||g==y%360?'-/|\\'[g/45%4].chr: (x..y)===g ?'*':' '};puts}
Nicer-formatted version:
x, y, r = gets.scan(/\d+/).map{|z| z.to_i}
s = (-r..r)
s.each {|a|
s.each {|b|
g = (((Math::atan2(-a,b) / Math::PI) * 180) / 1) % 360
print ((a | b) == 0) ? 'o' :
(g == x || g == (y % 360)) ? '-/|\\'[(g / 45) % 4].chr :
((x..y) === g) ? '*' : ' '
}
puts
}
I'm sure someone out there who got more sleep than I did can condense this more...
Edit 1: Switched if statements in inner loop to nested ? : operator
Edit 2: Stored range to intermediate variable (thanks Adrian), used stdin instead of CLI params (thanks for the clarification Jon), eliminated array in favor of direct output, fixed bug where an ending angle of 360 wouldn't display a line, removed some un-needed parentheses, used division for rounding instead of .round, used modulo instead of conditional add
Ruby, 168 characters
Requires Ruby 1.9 to work
s,e,r=gets.scan(/\d+/).map &:to_i;s/=45;e/=45;G=-r..r;G.map{|y|G.map{|x|a=Math.atan2(-y,x)/Math::PI*4%8;print x|y!=0?a==s||a==e%8?'-/|\\'[a%4]:a<s||a>e ?' ':8:?o};puts}
Readable version:
start, _end, radius = gets.scan(/\d+/).map &:to_i
start /= 45
_end /= 45
(-radius..radius).each {|y|
(-radius..radius).each {|x|
angle = Math.atan2(-y, x)/Math::PI * 4 % 8
print x|y != 0 ? angle==start || angle==_end%8 ? '-/|\\'[angle%4] : angle<start || angle>_end ? ' ' : 8 : ?o
}
puts
}
Perl - 388 characters
Since it wouldn't be fair to pose a challenge I couldn't solve myself, here's a solution that uses string substitution instead of trigonometric functions, and making heavy use of your friendly neighbourhood Perl's ability to treat barewords as strings. It's necessarily a little long, but perhaps interesting for the sake of uniqueness:
($x,$y,$r)=split/\D/,<>;for(0..$r-1){$t=$r-1-$_;
$a.=L x$_.D.K x$t.C.J x$t.B.I x$_."\n";
$b.=M x$t.F.N x$_.G.O x$_.H.P x$t."\n"}
$_=$a.E x$r.o.A x$r."\n".$b;$x/=45;$y/=45;$S=' ';
sub A{$v=$_[0];$x==$v||$y==$v?$_[1]:$x<$v&&$y>$v?x:$S}
sub B{$x<=$_[0]&&$y>$_[0]?x:$S}
#a=!$x||$y==8?'-':$S;
push#a,map{A$_,'\\'.qw(- / | \\)[$_%4]}1..7;
push#a,!$x?x:$S,map{B$_}1..7;
eval"y/A-P/".(join'',#a)."/";print
All newlines are optional. It's fairly straightforward:
Grab user input.
Build the top ($a) and bottom ($b) parts of the pattern.
Build the complete pattern ($_).
Define a sub A to get the fill character for an angle.
Define a sub B to get the fill character for a region.
Build an array (#a) of substitution characters using A and B.
Perform the substitution and print the results.
The generated format looks like this, for R = 4:
DKKKCJJJB
LDKKCJJBI
LLDKCJBII
LLLDCBIII
EEEEoAAAA
MMMFGHPPP
MMFNGOHPP
MFNNGOOHP
FNNNGOOOH
Where A-H denote angles and I-P denote regions.
(Admittedly, this could probably be golfed further. The operations on #a gave me incorrect output when written as one list, presumably having something to do with how map plays with $_.)
C# - 325 319 chars
using System;class P{static void Main(){var s=Console.ReadLine().Split(' ');
var d=s[0].Split('-');int l=s[1][0]-48,x,y,r,a=int.Parse(d[0]),b=int.Parse(d[1]);
for(y=l;y>=-l;y--)for(x=-l;x<=l;)Console.Write((x==0&&y==0?'o':a<=(r=((int)
(Math.Atan2(y,x)*57.3)+360)%360)&&r<b||r==b%360?
#"-/|\"[r/45%4]:' ')+(x++==l?"\n":""));}}
Newlines not significant.
Sample input/output
45-180 8
\||||||||////////
\\|||||||///////
\\\||||||//////
\\\\|||||/////
\\\\\||||////
\\\\\\|||///
\\\\\\\||//
\\\\\\\\|/
--------o
135-360 5
\
\\
\\\
\\\\
\\\\\
-----o-----
----/|\\\\\
---//||\\\\
--///|||\\\
-////||||\\
/////|||||\
Java - 304 chars
class A{public static void main(String[]a){String[]b=a[0].split("-");int e=new Integer(b[1]),r=new Integer(a[1]),g,x,y=r;for(;y>=-r;y--)for(x=-r;x<=r;)System.out.print((x==0&y==0?'o':new Integer(b[0])<=(g=((int)(Math.atan2(y,x)*57.3)+360)%360)&g<e|g==e%360?"-/|\\".charAt(g/45%4):' ')+(x++<r?"":"\n"));}}
More readable version:
class A{
public static void main(String[]a){
String[]b=a[0].split("-");
int e=new Integer(b[1]),r=new Integer(a[1]),g,x,y=r;
for(;y>=-r;y--)for(x=-r;x<=r;)System.out.print((
x==0&y==0
?'o'
:new Integer(b[0])<=(g=((int)(Math.atan2(y,x)*57.3)+360)%360)&g<e|g==e%360
?"-/|\\".charAt(g/45%4)
:' '
)+(x++<r?"":"\n"));
}
}
C (902 byte)
This doesn't use trigonometric functions (like the original perl version), so it's quite ``bloated''. Anyway, here is my first code-golf submission:
#define V(r) (4*r*r+6*r+3)
#define F for(i=0;i<r;i++)
#define C ;break;case
#define U p-=2*r+2,
#define D p+=2*r+2,
#define R *++p=
#define L *--p=
#define H *p='|';
#define E else if
#define G(a) for(j=0;j<V(r)-1;j++)if(f[j]==i+'0')f[j]=a;
#define O(i) for(i=0;i<2*r+1;i++){
main(int i,char**v){char*p,f[V(8)];
int j,m,e,s,x,y,r;p=*++v;x=atoi(p);while(*p!=45)p++;
char*h="0123";y=atoi(p+1);r=atoi(*++v);
for(p=f+2*r+1;p<f+V(r);p+=2*r+2)*p=10;
*(p-2*r-2)=0;x=x?x/45:x;y/=45;s=0;e=2*r;m=r;p=f;O(i)O(j)
if(j>e)*p=h[0];E(j>m)*p=h[1];E(j>s)*p=h[2];else*p=h[3];p++;}
if(i+1==r){h="7654";m--;e--;}E(i==r){s--;}E(i>r){s--;e++;}
else{s++;e--;}p++;}for(p=f+V(r)/2-1,i=0;i<r;i++)*++p=48;
for(i=0;i<8;i++)if(i>=x&&i<y){G(64);}else G(32);
y=y==8?0:y;q:p=f+V(r)/2-1;*p='o';switch(x){
C 0:F R 45 C 1:F U R 47 C 2:F U H C 3:F U L 92
C 4:F L 45 C 5:F D L 47 C 6:F D H C 7:F D R 92;}
if(y!=8){x=y;y=8;goto q;}puts(f);}
also, the #defines look rather ugly, but they save about 200 bytes so I kept them in, anyway. It is valid ANSI C89/C90 and compiles with very few warnings (two about atoi and puts and two about crippled form of main).
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
The Challenge
Guidelines for code-golf on SO
The shortest code by character count to display a representation of a circle of radius R using the *character, followed by an approximation of π.
Input is a single number, R.
Since most computers seem to have almost 2:1 ratio you should only output lines where y is odd. This means that when R is odd you should print R-1 lines. There is a new testcase for R=13 to clarify.
eg.
Input
5
Output Correct Incorrect
3 ******* 4 *******
1 ********* 2 *********
-1 ********* 0 ***********
-3 ******* -2 *********
2.56 -4 *******
3.44
Edit: Due to widespread confusion caused by odd values of R, any solutions that pass the 4 test cases given below will be accepted
The approximation of π is given by dividing twice the number of * characters by R².
The approximation should be correct to at least 6 significant digits.
Leading or trailing zeros are permitted, so for example any of 3, 3.000000, 003 is accepted for the inputs of 2 and 4.
Code count includes input/output (i.e., full program).
Test Cases
Input
2
Output
***
***
3.0
Input
4
Output
*****
*******
*******
*****
3.0
Input
8
Output
*******
*************
***************
***************
***************
***************
*************
*******
3.125
Input
10
Output
*********
***************
*****************
*******************
*******************
*******************
*******************
*****************
***************
*********
3.16
Bonus Test Case
Input
13
Output
*************
*******************
*********************
***********************
*************************
*************************
*************************
*************************
***********************
*********************
*******************
*************
2.98224852071
C: 131 chars
(Based on the C++ solution by Joey)
main(i,j,c,n){for(scanf("%d",&n),c=0,i|=-n;i<n;puts(""),i+=2)for(j=-n;++j<n;putchar(i*i+j*j<n*n?c++,42:32));printf("%g",2.*c/n/n);}
(Change the i|=-n to i-=n to remove the support of odd number cases. This merely reduces char count to 130.)
As a circle:
main(i,j,
c,n){for(scanf(
"%d",&n),c=0,i=1|
-n;i<n;puts(""),i+=
0x2)for(j=-n;++j<n;
putchar(i*i+j*j<n*n
?c++,0x02a:0x020));
printf("%g",2.*c/
n/n);3.1415926;
5358979;}
XSLT 1.0
Just for fun, here's an XSLT version. Not really code-golf material, but it solves the problem in a weird-functional-XSLT-kind of way :)
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" >
<xsl:output method="html"/>
<!-- Skip even lines -->
<xsl:template match="s[#y mod 2=0]">
<xsl:variable name="next">
<!-- Just go to next line.-->
<s R="{#R}" y="{#y+1}" x="{-#R}" area="{#area}"/>
</xsl:variable>
<xsl:apply-templates select="msxsl:node-set($next)"/>
</xsl:template>
<!-- End of the line?-->
<xsl:template match="s[#x > #R]">
<xsl:variable name="next">
<!-- Go to next line.-->
<s R="{#R}" y="{#y+1}" x="{-#R}" area="{#area}"/>
</xsl:variable><!-- Print LF-->
<xsl:apply-templates
select="msxsl:node-set($next)"/>
</xsl:template>
<!-- Are we done? -->
<xsl:template match="s[#y > #R]">
<!-- Print PI approximation -->
<xsl:value-of select="2*#area div #R div #R"/>
</xsl:template>
<!-- Everything not matched above -->
<xsl:template match="s">
<!-- Inside the circle?-->
<xsl:variable name="inside" select="#x*#x+#y*#y < #R*#R"/>
<!-- Print "*" or " "-->
<xsl:choose>
<xsl:when test="$inside">*</xsl:when>
<xsl:otherwise> </xsl:otherwise>
</xsl:choose>
<xsl:variable name="next">
<!-- Add 1 to area if we're inside the circle. Go to next column.-->
<s R="{#R}" y="{#y}" x="{#x+1}" area="{#area+number($inside)}"/>
</xsl:variable>
<xsl:apply-templates select="msxsl:node-set($next)"/>
</xsl:template>
<!-- Begin here -->
<xsl:template match="/R">
<xsl:variable name="initial">
<!-- Initial state-->
<s R="{number()}" y="{-number()}" x="{-number()}" area="0"/>
</xsl:variable>
<pre>
<xsl:apply-templates select="msxsl:node-set($initial)"/>
</pre>
</xsl:template>
</xsl:stylesheet>
If you want to test it, save it as pi.xslt and open the following XML file in IE:
<?xml version="1.0"?>
<?xml-stylesheet href="pi.xslt" type="text/xsl" ?>
<R>
10
</R>
Perl, 95 96 99 106 109 110 119 characters:
$t+=$;=1|2*sqrt($r**2-($u-2*$_)**2),say$"x($r-$;/2).'*'x$;for 0..
($u=($r=<>)-1|1);say$t*2/$r**2
(The newline can be removed and is only there to avoid a scrollbar)
Yay! Circle version!
$t+=$;=
1|2*sqrt($r**
2-($u-2*$_)**2)
,say$"x($r-$;/2
).'*'x$;for 0..
($u=($r=<>)-1|1
);$pi=~say$t*
2/$r**2
For the uninitiated, the long version:
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
# Read the radius from STDIN
my $radius = <>;
# Since we're only printing asterisks on lines where y is odd,
# the number of lines to be printed equals the size of the radius,
# or (radius + 1) if the radius is an odd number.
# Note: we're always printing an even number of lines.
my $maxline = ($radius - 1) | 1;
my $surface = 0;
# for ($_ = 0; $_ <= $maxline; $_++), if you wish
for (0 .. $maxline) {
# First turn 0 ... N-1 into -(N/2) ... N/2 (= Y-coordinates),
my $y = $maxline - 2*$_;
# then use Pythagoras to see how many stars we need to print for this line.
# Bitwise OR "casts" to int; and: 1 | int(2 * x) == 1 + 2 * int(x)
my $stars = 1 | 2 * sqrt($radius**2-$y**2);
$surface += $stars;
# $" = $LIST_SEPARATOR: default is a space,
# Print indentation + stars
# (newline is printed automatically by say)
say $" x ($radius - $stars/2) . '*' x $stars;
}
# Approximation of Pi based on surface area of circle:
say $surface*2/$radius**2;
FORTRAN - 101 Chars
$ f95 piday.f95 -o piday && echo 8 | ./piday
READ*,N
DO I=-N,N,2
M=(N*N-I*I)**.5
PRINT*,(' ',J=1,N-M),('*',J=0,M*2)
T=T+2*J
ENDDO
PRINT*,T/N/N
END
READ*,N
K=N/2*2;DO&
I=1-K,N,2;M=&
(N*N-I*I)**.5;;
PRINT*,(' ',J=&
1,N-M),('*',J=&
0,M*2);T=T+2*J;
ENDDO;PRINT*&
,T/N/N;END;
!PI-DAY
x86 Machine Code: 127 bytes
Intel Assembler: 490 chars
mov si,80h
mov cl,[si]
jcxz ret
mov bx,10
xor ax,ax
xor bp,bp
dec cx
a:mul bx
mov dl,[si+2]
sub dl,48
cmp dl,bl
jae ret
add ax,dx
inc si
loop a
mov dl,al
inc dl
mov dh,al
add dh,dh
mov ch,dh
mul al
mov di,ax
x:mov al,ch
sub al,dl
imul al
mov si,ax
mov cl,dh
c:mov al,cl
sub al,dl
imul al
add ax,si
cmp ax,di
mov al,32
ja y
or al,bl
add bp,2
y:int 29h
dec cl
jnz c
mov al,bl
int 29h
mov al,13
int 29h
sub ch,2
jnc x
mov ax,bp
cwd
mov cl,7
e:div di
cmp cl,6
jne z
pusha
mov al,46
int 29h
popa
z:add al,48
int 29h
mov ax,bx
mul dx
jz ret
dec cl
jnz e
ret
This version handles the bonus test case as well and is 133 bytes:
mov si,80h
mov cl,[si]
jcxz ret
mov bx,10
xor ax,ax
xor bp,bp
dec cx
a:mul bx
mov dl,[si+2]
sub dl,48
cmp dl,bl
jae ret
add ax,dx
inc si
loop a
mov dl,al
rcr dl,1
adc dl,dh
add dl,dl
mov dh,dl
add dh,dh
dec dh
mov ch,dh
mul al
mov di,ax
x:mov al,ch
sub al,dl
imul al
mov si,ax
mov cl,dh
c:mov al,cl
sub al,dl
imul al
add ax,si
cmp ax,di
mov al,32
jae y
or al,bl
add bp,2
y:int 29h
dec cl
jnz c
mov al,bl
int 29h
mov al,13
int 29h
sub ch,2
jnc x
mov ax,bp
cwd
mov cl,7
e:div di
cmp cl,6
jne z
pusha
mov al,46
int 29h
popa
z:add al,48
int 29h
mov ax,bx
mul dx
jz ret
dec cl
jnz e
ret
Python: 101 104 107 110 chars
Based on the other Python version by Nicholas Riley.
r=input()
t=0
i=1
exec"n=1+int((2*i*r-i*i)**.5)*2;t+=2.*n/r/r;print' '*(r-n/2)+'*'*n;i+=2;"*r
print t
Credits to AlcariTheMad for some of the math.
Ah, the odd-numbered ones are indexed with zero as the middle, explains everything.
Bonus Python: 115 chars (quickly hacked together)
r=input()
t=0
i=1
while i<r*2:n=1+int((2*i*r-i*i)**.5)*2;t+=2.*n/r/r;print' '*(r-n/2)+'*'*n;i+=2+(r-i==2)*2
print t
In dc: 88 and 93 93 94 96 102 105 129 138 141 chars
Just in case, I am using OpenBSD and some supposedly non-portable extensions at this point.
93 chars. This is based on same formula as FORTRAN solution (slightly different results than test cases). Calculates X^2=R^2-Y^2 for every Y
[rdPr1-d0<p]sp1?dsMdd*sRd2%--
[dd*lRr-vddlMr-32rlpxRR42r2*lpxRRAP4*2+lN+sN2+dlM>y]
dsyx5klNlR/p
88 chars. Iterative solution. Matches test cases. For every X and Y checks if X^2+Y^2<=R^2
1?dsMdd*sRd2%--sY[0lM-[dd*lYd*+lRr(2*d5*32+PlN+sN1+dlM!<x]dsxxAPlY2+dsYlM>y]
dsyx5klNlR/p
To run dc pi.dc.
Here is an older annotated version:
# Routines to print '*' or ' '. If '*', increase the counter by 2
[lN2+sN42P]s1
[32P]s2
# do 1 row
# keeping I in the stack
[
# X in the stack
# Calculate X^2+Y^2 (leave a copy of X)
dd*lYd*+
#Calculate X^2+Y^2-R^2...
lR-d
# .. if <0, execute routine 1 (print '*')
0>1
# .. else execute routine 2 (print ' ')
0!>2
# increment X..
1+
# and check if done with line (if not done, recurse)
d lM!<x
]sx
# Routine to cycle for the columns
# Y is on the stack
[
# push -X
0lM-
# Do row
lxx
# Print EOL
10P
# Increment Y and save it, leaving 2 copies
lY 2+ dsY
# Check for stop condition
lM >y
]sy
# main loop
# Push Input value
[Input:]n?
# Initialize registers
# M=rows
d sM
# Y=1-(M-(M%2))
dd2%-1r-sY
# R=M^2
d*sR
# N=0
0sN
[Output:]p
# Main routine
lyx
# Print value of PI, N/R
5klNlR/p
Powershell, 119 113 109 characters
($z=-($n=$args[($s=0)])..$n)|?{$_%2}|%{$l="";$i=$_
$z|%{$l+=" *"[$i*$i+$_*$_-lt$n*$n-and++$s]};$l};2*$s/$n/$n
and here's a prettier version:
( $range = -( $R = $args[ ( $area = 0 ) ] ) .. $R ) |
where { $_ % 2 } |
foreach {
$line = ""
$i = $_
$range | foreach {
$line += " *"[ $i*$i + $_*$_ -lt $R*$R -and ++$area ]
}
$line
}
2 * $area / $R / $R
HyperTalk: 237 characters
Indentation is not required nor counted. It is added for clarity. Also note that HyperCard 2.2 does accept those non-ASCII relational operators I used.
function P R
put""into t
put 0into c
repeat with i=-R to R
if i mod 2≠0then
repeat with j=-R to R
if i^2+j^2≤R^2then
put"*"after t
add 1to c
else
put" "after t
end if
end repeat
put return after t
end if
end repeat
return t&2*c/R/R
end P
Since HyperCard 2.2 doesn't support stdin/stdout, a function is provided instead.
C#: 209 202 201 characters:
using C=System.Console;class P{static void Main(string[]a){int r=int.Parse(a[0]),s=0,i,x,y;for(y=1-r;y<r;y+=2){for(x=1-r;x<r;s+=i)C.Write(" *"[i=x*x+++y*y<=r*r?1:0]);C.WriteLine();}C.Write(s*2d/r/r);}}
Unminified:
using C = System.Console;
class P {
static void Main(string[] arg) {
int r = int.Parse(arg[0]), sum = 0, inside, x, y;
for (y = 1 - r; y < r; y += 2) {
for (x = 1 - r; x < r; sum += inside)
C.Write(" *"[inside = x * x++ + y * y <= r * r ? 1 : 0]);
C.WriteLine();
}
C.Write(sum * 2d / r / r);
}
}
Haskell 139 145 147 150 230 chars:
x True=' ';x _='*'
a n=unlines[[x$i^2+j^2>n^2|j<-[-n..n]]|i<-[1-n,3-n..n]]
b n=a n++show(sum[2|i<-a n,i=='*']/n/n)
main=readLn>>=putStrLn.b
Handling the odd numbers: 148 chars:
main=do{n<-readLn;let{z k|k<n^2='*';z _=' ';c=[[z$i^2+j^2|j<-[-n..n]]|i<-[1,3..n]];d=unlines$reverse c++c};putStrLn$d++show(sum[2|i<-d,i=='*']/n/n)}
150 chars:
(Based on the C version.)
a n=unlines[concat[if i^2+j^2>n^2then" "else"*"|j<-[-n..n]]|i<-[1-n,3-n..n]]
main=do n<-read`fmap`getLine;putStr$a n;print$2*sum[1|i<-a n,i=='*']/n/n
230 chars:
main=do{r<-read`fmap`getLine;let{p=putStr;d=2/fromIntegral r^2;l y n=let c m x=if x>r then p"\n">>return m else if x*x+y*y<r*r then p"*">>c(m+d)(x+1)else p" ">>c m(x+1)in if y>r then print n else c n(-r)>>=l(y+2)};l(1-r`mod`2-r)0}
Unminified:
main = do r <- read `fmap` getLine
let p = putStr
d = 2/fromIntegral r^2
l y n = let c m x = if x > r
then p "\n" >> return m
else if x*x+y*y<r*r
then p "*" >> c (m+d) (x+1)
else p " " >> c m (x+1)
in if y > r
then print n
else c n (-r) >>= l (y+2)
l (1-r`mod`2-r) 0
I was kinda hoping it would beat some of the imperative versions, but I can't seem to compress it any further at this point.
Ruby, 96 chars
(based on Guffa's C# solution):
r=gets.to_f
s=2*t=r*r
g=1-r..r
g.step(2){|y|g.step{|x|putc' * '[i=t<=>x*x+y*y];s+=i}
puts}
p s/t
109 chars (bonus):
r=gets.to_i
g=-r..r
s=g.map{|i|(g.map{|j|i*i+j*j<r*r ?'*':' '}*''+"\n")*(i%2)}*''
puts s,2.0/r/r*s.count('*')
PHP: 117
Based on dev-null-dweller
for($y=1-$r=$argv[1];$y<$r;$y+=2,print"\n")for($x=1-$r;$x<$r;$x++)echo$r*$r>$x*$x+$y*$y&&$s++?'*':' ';echo$s*2/$r/$r;
You guys are thinking way too hard.
switch (r) {
case 1,2:
echo "*"; break;
case 3,4:
echo " ***\n*****\n ***"; break;
// etc.
}
J: 47, 46, 45
Same basic idea as other solutions, i.e. r^2 <= x^2 + y^2, but J's array-oriented notation simplifies the expression:
c=:({&' *',&":2*+/#,%#*#)#:>_2{.\|#j./~#i:#<:
You'd call it like c 2 or c 8 or c 10 etc.
Bonus: 49
To handle odd input, e.g. 13, we have to filter on odd-valued x coordinates, rather than simply taking every other row of output (because now the indices could start at either an even or odd number). This generalization costs us 4 characters:
c=:*:({&' *'#],&":2%(%+/#,))]>(|#j./~2&|#])#i:#<:
Deminimized version:
c =: verb define
pythag =. y > | j./~ i:y-1 NB. r^2 > x^2 + y^2
squished =. _2 {.\ pythag NB. Odd rows only
piApx =. (2 * +/ , squished) % y*y
(squished { ' *') , ": piApx
)
Improvements and generalizations due to Marshall Lochbam on the J Forums.
Python: 118 characters
Pretty much a straightforward port of the Perl version.
r=input()
u=r+r%2
t=0
for i in range(u):n=1+2*int((r*r-(u-1-2*i)**2)**.5);t+=n;print' '*(r-n/2-1),'*'*n
print 2.*t/r/r
C++: 169 characters
#include <iostream>
int main(){int i,j,c=0,n;std::cin>>n;for(i=-n;i<=n;i+=2,std::cout<<'\n')for(j=-n;j<=n;j++)std::cout<<(i*i+j*j<=n*n?c++,'*':' ');std::cout<<2.*c/n/n;}
Unminified:
#include <iostream>
int main()
{
int i,j,c=0,n;
std::cin>>n;
for(i=-n;i<=n;i+=2,std::cout<<'\n')
for(j=-n;j<=n;j++)
std::cout<<(i*i+j*j<=n*n?c++,'*':' ');
std::cout<<2.*c/n/n;
}
(Yes, using std:: instead of using namespace std uses less characters)
The output here doesn't match the test cases in the original post, so here's one that does (written for readability). Consider it a reference implementation (if Poita_ doesn't mind):
#include <iostream>
using namespace std;
int main()
{
int i, j, c=0, n;
cin >> n;
for(i=-n; i<=n; i++) {
if (i & 1) {
for(j=-n; j<=n; j++) {
if (i*i + j*j <= n*n) {
cout << '*';
c++;
} else {
cout << ' ';
}
}
cout << '\n';
}
}
cout << 2.0 * c / n / n << '\n';
}
C++: 168 characters (with output I believe is correct)
#include <iostream>
int main(){int i,j,c=0,n;std::cin>>n;for(i=-n|1;i<=n;i+=2,std::cout<<"\n")for(j=-n;j<=n;j++)std::cout<<" *"[i*i+j*j<=n*n&&++c];std::cout<<2.*c/n/n;}
PHP: 126 132 138
(based on Guffa C# solution)
126:
for($y=1-($r=$argv[1]);$y<$r;$y+=2,print"\n")for($x=1-$r;$x<$r;$s+=$i,++$x)echo($i=$x*$x+$y*$y<=$r*$r)?'*':' ';echo$s*2/$r/$r;
132:
for($y=1-($r=$argv[1]);$y<$r;$y+=2){for($x=1-$r;$x<$r;#$s+=$i,++$x)echo($i=$x*$x+$y*$y<=$r*$r?1:0)?'*':' ';echo"\n";}echo$s*2/$r/$r;
138:
for($y=1-($r=$argv[1]);$y<$r;$y+=2){for($x=1-$r;$x<$r;#$s+=$i){$t=$x;echo($i=$t*$x++ +$y*$y<=$r*$r?1:0)?'*':' ';}echo"\n";}echo$s*2/$r/$r;
Current full:
for( $y = 1 - ( $r = $argv[1]); $y < $r; $y += 2, print "\n")
for( $x = 1-$r; $x < $r; $s += $i, ++$x)
echo( $i = $x*$x + $y*$y <= $r*$r) ? '*' : ' ';
echo $s*2 /$r /$r;
Can be without # before first $s but only with error_reporting set to 0 (Notice outputs is messing the circle)
Ruby 1.8.x, 93
r=$_.to_f
q=0
e=r-1
(p(('*'*(n=1|2*(r*r-e*e)**0.5)).center r+r)
q+=n+n
e-=2)while-r<e
p q/r/r
Run with $ ruby -p piday
APL: 59
This function accepts a number and returns the two expected items. Works correctly in bonus cases.
{⍪(⊂' *'[1+m]),q÷⍨2×+/,m←(2|v)⌿(q←⍵*2)>v∘.+v←2*⍨⍵-⍳1+2×⍵-1}
Dialect is Dyalog APL, with default index origin. Skill level is clueless newbie, so if any APL guru wants to bring it down to 10 characters, be my guest!
You can try it online on Try APL, just paste it in and put a number after it:
{⍪(⊂' *'[1+m]),q÷⍨2×+/,m←(2|v)⌿(q←⍵*2)>v∘.+v←2*⍨⍵-⍳1+2×⍵-1} 13
*************
*******************
*********************
***********************
*************************
*************************
*************************
*************************
***********************
*********************
*******************
*************
2.98225
And a bash entry: 181 186 190 chars
for((y=-(r=$1,r/2*2);y<=r;y+=2));do for((x=-r;x<=r;++x));do((x*x+y*y<r*r))&&{((++n));echo -n '*';}||echo -n " ";((x<r))||echo;done;done;((s=1000,p=n*2*s/r/r,a=p/s,b=p%s));echo $a.$b
Run with e.g. bash py.sh 13
Python: 148 characters.
Failed (i.e. not short enough) attempt to abuse the rules and hardcode the test cases, as I mentioned in reply to the original post. Abusing it with a more verbose language may have been easier:
a=3.0,3.125,3.16
b="1","23","3677","47899"
r=input()
for i in b[r/3]+b[r/3][::-1]:q=1+2*int(i);print ' '*(int(b[r/3][-1])-int(i))+'*'*q
print a[r/5]
bc: 165, 127, 126 chars
Based on the Python version.
r=read()
for(i=-1;r*2>i+=2;scale=6){n=sqrt(2*i*r-i*i)
scale=0
n=1+n/1*2
j=r-n/2
t+=2*n
while(j--)" "
while(n--)"*"
"
"}
t/r/r
(New line after the last line cannot be omitted here.)
JavaScript (SpiderMonkey) - 118 chars
This version accepts input from stdin and passes the bonus test cases
r=readline()
for(t=0,i=-r;i<r;i++)if(i%2){for(s='',j=-r;j<r;j++){t+=q=i*i+j*j<r*r
s+=q?'*':' '}print(s)}print(t*2/r/r)
Usage: cat 10 | js thisfile.js -- jsbin preview adds an alias for print/readline so you can view in browser
Javascript: 213 163
Updated
r=10;m=Math;a=Array;t=0;l=document;for(i=-r;i<r;i+=2){w=m.floor(m.sqrt(r*r-i*i)*2);t+=w*2;l.writeln(a(m.round(r-w/2)).join(' ')+a(w).join('*'));}l.writeln(t/(r*r))
Nobody said it had to render correctly in the browser - just the output. As such I've removed the pre tags and optimised it further. To view the output you need to view generated source or set your stylesheet accordingly. Pi is less accurate this way, but it's now to spec.
r=10;m=Math;a=Array;t=0;s='';for(i=-r;i<r;i++){w=m.floor((m.sqrt(m.pow(r,2)-m.pow(i,2)))*2);t+=w;if(i%2){z=a(m.round(r-w/2)).join(' ')+a(w).join('*');s+=z+'\n';}}document.write('<pre>'+(s+(t/m.pow(r,2)))+'</pre>')
Unminified:
r=10;
m=Math;
a=Array;
t=0;
s='';
for(i=-r;i<r;i++){
w=m.floor((m.sqrt(m.pow(r,2)-m.pow(i,2)))*2);
t+=w;
if(i%2){
z=a(m.round(r-w/2)).join(' ')+a(w).join('*');
s+=z+'\n';
}
}
document.write('<pre>'+(s+(t/m.pow(r,2)))+'</pre>');
Java: 234
class C{public static void main(String[] a){int x,y,s=0,r=Integer.parseInt(a[0]);for(y=1-r;y<r;y+=2){for(x=1-r;x<r;++x){boolean b=x*x+y*y<=r*r;s+=b?1:0;System.out.print(b?'*':' ');}System.out.println();}System.out.println(s*2d/r/r);}}
Unminified:
class C{
public static void main(String[] a){
int x,y,s=0,r=Integer.parseInt(a[0]);
for(y=1-r;y<r;y+=2){
for(x=1-r;x<r;++x) {
boolean b=x*x+y*y<=r*r;
s+=b?1:0;
System.out.print(b?'*':' ');
}
System.out.println();
}
System.out.println(s*2d/r/r);
}
}
GAWK: 136, 132, 126, 125 chars
Based on the Python version.
{r=$1
for(i=-1;r*2>i+=2;print""){n=1+int((2*i*r-i*i)**.5)*2
t+=2*n/r/r
printf"%*s",r-n/2,""
while(n--)printf"%c","*"}print t}
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
The challenge
The shortest code by character count that will generate a beehive from user input.
A beehive is defined a a grid of hexagons in a size inputted by the user as two positive numbers greater than zero (no need to validate input). The first number (W) represents the width of the beehive - or - how many hexagons are on each row. The second number (H) represents the height of the beehive - or - how many hexagons are on each column.
A Single hexagon is made from three ASCII characters: _, / and \, and three lines:
__
/ \
\__/
Hexagons complete each other: the first column of the beehive will be 'low', and the second will be high - alternating and repeating in the same pattern forming W hexagons. This will be repeated H times to form a total of WxH hexagons.
Test cases:
Input:
1 1
Output:
__
/ \
\__/
Input:
4 2
Output:
__ __
__/ \__/ \
/ \__/ \__/
\__/ \__/ \
/ \__/ \__/
\__/ \__/
Input:
2 5
Output:
__
__/ \
/ \__/
\__/ \
/ \__/
\__/ \
/ \__/
\__/ \
/ \__/
\__/ \
/ \__/
\__/
Input:
11 3
Output:
__ __ __ __ __
__/ \__/ \__/ \__/ \__/ \__
/ \__/ \__/ \__/ \__/ \__/ \
\__/ \__/ \__/ \__/ \__/ \__/
/ \__/ \__/ \__/ \__/ \__/ \
\__/ \__/ \__/ \__/ \__/ \__/
/ \__/ \__/ \__/ \__/ \__/ \
\__/ \__/ \__/ \__/ \__/ \__/
Code count includes input/output (i.e full program).
Perl, 99 characters
#P=map{$/.substr$".'__/ \\'x99,$_,$W||=1+3*pop}0,(3,6)x pop;
chop$P[0-$W%2];print" __"x($W/6),#P
Last edit: Saved one character replacing -($W%2) with 0-$W%2 (thanks A. Rex)
Explanation:
For width W and height H, the output is 2+2 * H lines long and 3 * W+1 characters wide, with a lot of repetition in the middle of the output.
For convenience, we let $W be 3 * W + 1, the width of the output in characters.
The top line consists of the pattern " __", repeated W/2 == $W/6 times.
The even numbered lines consist of the repeating pattern "\__/ ", truncated to $W characters. The second line of output is a special case, where the first character of the second line should be a space instead of a \.
The odd numbered lines consist of the repeating pattern "/ \__", truncated to $W characters.
We construct a string: " " . "__/ \" x 99. Note that the beginning of this string is the desired output for the second line. This line starting at position 3 is the desired output for the odd lines, and starting at position 6 for the even numbered lines.
The LIST argument to the map call begins with 0 and is followed by H repetitions of (3,6). The map call creates a list of the substrings that begin at the appropriate positions and are $W = 3 * W + 1 characters long.
There is one more adjustment to make before printing the results. If W is odd, then there is an extra character on the second line ($P[0]) that needs to be chopped off. If W is even, then there is an extra character on the bottom line ($P[-1]) to chop.
Python 2.6 - 144 characters including newlines
I can save about 20 more characters if the inputs are allowed to be comma separated.
C,R=map(int,raw_input().split())
print C/2*" __"+"\n "+("__/ \\"*99)[:3*C-C%2]
r=0
exec'r+=3;print ("\__/ "*99)[r:r+3*C+1-r/6/R*~C%2];'*2*R
The version that takes input from the command line is 4 more bytes:
import sys
C,R=map(int,sys.argv[1:])
print C/2*" __"+"\n "+("__/ \\"*99)[:3*C-C%2]
r=0
exec'r+=3;print ("\__/ "*99)[r:r+3*C+1-r/6/R*~C%2];'*2*R
C89 (136 characters)
x;y;w;main(h){for(h=scanf("%d%d",&w,&h)*h+2;y++
<h;++x)putchar(x>w*3-(y==(w&1?2:h))?x=-1,10:
"/ \\__"[--y?y-1|x?(x+y*3)%6:1:x%6<4?1:5]);}
Perl, 160 characters
$w=shift;for$h(-1..2*shift){push#a,join'',(('\__','/ ')x($w+$h))[$h..$w+$h]}
$a[0]=~y#\\/# #;$a[1]=~s/./ /;s/_*$//for#a;$a[$w%2||$#a]=~s/. *$//;print$_,$/for#a
No cleverness involved at all: just fill the array with characters, then weed out the ones that look ugly.
strager's masterpiece is only 137 characters when ported to Perl, but all credit should go to him.
$w=shift;$\=$/;for$y(1..($h=2+2*shift)){print map+(split//,'_ \__/ ')
[$y-1?$y-2|$_?($_+$y%2*3)%6+2:1:$_%6<4],0..$w*3-!($w&1?$y-2:$y-$h)}
J, 143 characters
4(1!:2)~(10{a.)&,"1({.4 :0{:)".(1!:1)3
|:(18,(}:,32-+:#{:)3 3 8 1 1 10$~3*x){(,' '&(0})"1,' '&(0 1})"1)(,}."1)(}."1,}:"1)(3++:y)$"1'/\',:' _'
)
Using J feels very awkward when dealing with variable-length strings and the sort of console-oriented user interaction that is assumed in other languages. Still, I guess this is not too bad...
Stealing ideas once more (J is much easier to work with once you find a way of looking at the problem in an array-structured way), here's mobrule's masterpiece ported in 124 (ick, it's longer than the original):
4(1!:2)~({.4 :0{:)".(1!:1)3
(x}~' '_1}(x=.-1-+:2|x){])((10{a.),(' ',,99#'__/ \',:' __'){~(i.>:3*x)+])"0]595 0,3 6$~+:y
)
C#, 216 characters
class B{static void Main(string[]a){int b=0,i=0,w=int.Parse(a[0])+1,z=2*w*(int.Parse(a[1])+1);for(;i<z;b=(i%w+i/w)%2)System.Console.Write("\\/ "[i>w&(w%2>0?i<z-1:i!=2*w-1)?b>0?0:1:2]+(++i%w<1?"\n":b>0?"__":" "));}}
Less obfuscated:
class B{
static void Main(string[]a){
int b=0,
i=0,
w=int.Parse(a[0])+1,
z=2*w*(int.Parse(a[1])+1);
for(;i<z;b=(i%w+i/w)%2)
System.Console.Write(
"\\/ "[i>w&(w%2>0?i<z-1:i!=2*w-1)?b>0?0:1:2]
+
(++i%w<1?"\n":b>0?"__":" ")
);
}
}
I used the following method:
input: 4 2
cols: 0 00 1 11 2 22 3 33 4 44
row 0:" | | |__| | | |__| |"
1:" |__|/| |\|__|/| |\|"
2:"/| |\|__|/| |\|__|/|"
3:"\|__|/| |\|__|/| |\|"
4:"/| |\|__|/| |\|__|/|"
5:"\|__|/| |\|__|/| | |"
Iterate from zero to (W+1)*(H*2+1). The *2 is because each comb is 2 lines tall, and +1 to account for the first line and end of lines.
Render two "pieces" of a hexagon per iteration:
Decide between " ", "\", and "/" for the first part
Decide between "__", " ", and "\n" for the second part
The pattern is evident if you look at a large enough honeycomb. Half the logic is there only to address exceptions in the first row, the end of the second row, and the last cell.
Ruby, 164
$ ruby -a -p bh.rb
strager's masterpiece in Ruby...
w,h = $F; w=w.to_i
(1..(h = h.to_i * 2 + 2)).each { |y|
(0...(w * 3 + (y != ((w & 1) != 0 ? 2 : h) ? 1:0))).each { |x|
$> << ('_ \__/ ' [
y - 1 != 0 ?
(y - 2 | x) != 0 ?
(x + y % 2 * 3) % 6 + 2 : 1 : (x % 6 < 4) ? 1:0]).chr
}
$> << $/
}
aka
w,h=$F;w=w.to_i
(1..(h=h.to_i*2+2)).each{|y|(0...(w*3+(y!=((w&1)!=0?2:h)?1:0))).each{|x|$><<('_ \__/ '[y-1!=0?(y-2|x)!=0?(x+y%2*3)%6+2:1:(x%6<4)?1:0]).chr}
$><<$/}
NewLisp: 257 chars
I'm sure this is not an optimal solution:
(silent(define(i v)(println)(set v(int(read-line))))(i'w)(i'h)(set't(+(* 3 w)1))(set'l " __/ \\__/ ")(define(p s e(b 0))(println(slice(append(dup" "b)(dup(s 6 l)w))0 e)))(p 0 t)(p 4(- t(% w 2))1)(dotimes(n(- h 1))(p 6 t)(p 9 t))(p 6 t)(p 9(- t(%(+ w 1)2))))
Less obfuscated:
(silent
(define (i v)
(println)
(set v (int (read-line))))
(i 'w)
(i 'h)
(set 't (+ (* 3 w) 1))
(set 'l " __/ \\__/ ")
(define (p s e (b 0))
(println (slice (append (dup " " b) (dup (s 6 l) w)) 0 e)))
(p 0 t)
(p 4 (- t (% w 2)) 1)
(dotimes (n (- h 1))
(p 6 t)
(p 9 t))
(p 6 t)
(p 9 (- t(% (+ w 1)2))))
I'm sure I could write the loop differently and save two lines and a few characters, for instance, but it's late...
Golfscript, 88 characters
Based on the mobrule's solution. It was a lot of work to get it smaller than that one! Newlines are just for clarity.
~:r;:c 3*):W 6/" __"*n
[][0]r[3 6]*+{[" ""__/ \\"99*+>W<]+.},;
c 2%-1 1if:r%)[-1<]+r%
n*
Explanation:
~:r;,:c # read input into rows, columns
3 *):W # store c*3+1 into W
6 /" __"*n # write out " __" W/6 times, plus newline
[] # initialize output array
[0]r[3 6]*+ # create array [0] + [3,6] repeated r times
{ # for every entry in the input array...
[" ""__/ \\"99*+ # create the magic string
>W< # truncate it between [n:W], where n is the cur entry
]+ # store this line in the output array
.},; # repeat for every entry in array
# now to handle the extra cases:
c 2%-1 1if:r% # reverse the array if c is odd, do nothing if it's even
)[-1<] # take the last entry in the array, cut off the last char
+r% # put it back on the array, and un-reverse it
n* # now join the array with newlines
Here is my original entry at 118 characters:
Late entry, but it's 2nd smallest! (I'm just using these to learn Golfscript). Newlines are for clarity.
~:r;:c 2%:o;c 2/:b" __"*n:e
{e" ""\\"if"__/ \\"b*o{"__"e{"":e}"/"if}{"":e}if n
"/"" \\__/"b*o" \\"""if n}r*
"\\__/ "b o+*
C89 - 261 necessary chars
All white spaces can be removed. My solution uses rotation of the board...
x,y,W,h,B[999],*a,*b,*c,*d;
main(w){
for(scanf("%d%d",&h,&w);y<h;y++,*b++ = *c++ = 63)
for(x=0,
W=w*2+2-(h==1),
a=B+y*W*3+y%2,
b=a+W,
c=b+W,
d=c+W;x++<w;)
*a++ = 60,
*a++ = *d++ = 15,
*b++ = *c++ = 63,
*b++ = *c++ = 0,
*d++ = 60;
for(x=W;--x>=0;puts(""))
for(y=0;y<h*3+1;putchar(B[x+y++*W]+32));
}
F#, 303 chars
let[|x;y|]=System.Console.ReadLine().Split([|' '|])
let p=printf
let L s o e=p"%s"s;(for i in 1..int x do p"%s"(if i%2=1 then o else e));p"\n"
if int x>1 then L" "" "" __ ";L" ""__""/ \\"
else L" ""__"""
for i in 1..int y-1 do(L"/"" \\""__/";L"\\""__/"" \\")
L"/"" \\""__/"
L"""\\__/"" "
EDIT
Now that there are finally some other answers posted, I don't mind sharing a less-obfuscated version:
let [|sx;sy|] = System.Console.ReadLine().Split([|' '|])
let x,y = int sx, int sy
let Line n start odd even =
printf "%s" start
for i in 1..n do
printf "%s" (if i%2=1 then odd else even)
printfn ""
// header
if x > 1 then
Line x " " " " " __ "
Line x " " "__" "/ \\"
else
Line x " " "__" " "
// body
for i in 1..y-1 do
Line x "/" " \\" "__/"
Line x "\\" "__/" " \\"
// footer
Line x "/" " \\" "__/"
Line x "" "\\__/" " "
C# 377 chars
Didn't want to disappoint anyone waiting for the "funny" C# answer.
Unfortunately, it's not 250 lines though...;)
using System;
class P{
static void Main(string[] a){
int i,j,w=Int32.Parse(a[0]),h=Int32.Parse(a[1]);
string n="\n",e="",o=e,l="__",s=" ",r=s+s,b=#"\",f="/";
string[] t={r+r,l,b+l+f,r,l,f+r+b,e,f,b,s};
for(i=0;i<w;)o+=t[i++%2];
for(i=0;i<2*h;i++){
o+=n+(i%2==0?i!=0?b:s:e);
for(j=0;j<w;)
o+=t[((j+++i)%2)+4];
o+=i!=0?t[((w+i)%2)+6]:e;
}
o+=n;
for(i=0;i<w;)o+=t[i++%2+2];
Console.Write(o);
}
}
Groovy, #375 chars
Same logic & code that #markt implemented in c#, but have changed few places for Groovy :)
public class FunCode {
public static void main(a) {
int i,j,w=Integer.parseInt(a[0]),h=Integer.parseInt(a[1]);
String n="\n",e="",o=e,l="__",s=" ",r=s+s,b="\\",f="/";
def t=[r+r,l,b+l+f,r,l,f+r+b,e,f,b,s];
for(i=0;i<w;)o+=t[i++%2];
for(i=0;i<2*h;i++){
o+=n+(i%2==0?i!=0?b:s:e);
for(j=0;j<w;)
o+=t[((j+++i)%2)+4];
o+=i!=0?t[((w+i)%2)+6]:e;
}
o+=n;
for(i=0;i<w;)o+=t[i++%2+2]; println(o);
}
}
Lua, 227 characters
w,h,s=io.read("*n"),io.read("*n")*2+2," " for i=1,h do b=(i%2>0 and "/ \\__" or "\\__/ "):rep(w/2+1):sub(1,w*3+1) print(i==1 and b:gsub("[/\\]",s) or i==2 and b:gsub("^\\",s):gsub("/$",s) or i==h and b:gsub("\\$",s) or b) end
208 characters, when width and height are read from command line.
s,w,h=" ",... h=h*2+2 for i=1,h do b=(i%2>0 and "/ \\__" or "\\__/ "):rep(w/2+1):sub(1,w*3+1) print(i==1 and b:gsub("[/\\]",s) or i==2 and b:gsub("^\\",s):gsub("/$",s) or i==h and b:gsub("\\$",s) or b) end
Closed. This question needs to be more focused. It is not currently accepting answers.
Closed 8 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
The challenge
The shortest code by character count, that will input a string using only alphabetical characters (upper and lower case), numbers, commas, periods and question mark, and returns a representation of the string in Morse code.
The Morse code output should consist of a dash (-, ASCII 0x2D) for a long beep (AKA 'dah') and a dot (., ASCII 0x2E) for short beep (AKA 'dit').
Each letter should be separated by a space (' ', ASCII 0x20), and each word should be separated by a forward slash (/, ASCII 0x2F).
Morse code table:
alt text http://liranuna.com/junk/morse.gif
Test cases:
Input:
Hello world
Output:
.... . .-.. .-.. --- / .-- --- .-. .-.. -..
Input:
Hello, Stackoverflow.
Output:
.... . .-.. .-.. --- --..-- / ... - .- -.-. -.- --- ...- . .-. ..-. .-.. --- .-- .-.-.-
Code count includes input/output (that is, the full program).
C (131 characters)
Yes, 131!
main(c){for(;c=c?c:(c=toupper(getch())-32)?
"•ƒŒKa`^ZRBCEIQiw#S#nx(37+$6-2&#/4)'18=,*%.:0;?5"
[c-12]-34:-3;c/=2)putch(c/2?46-c%2:0);}
I eeked out a few more characters by combining the logic from the while and for loops into a single for loop, and by moving the declaration of the c variable into the main definition as an input parameter. This latter technique I borrowed from strager's answer to another challenge.
For those trying to verify the program with GCC or with ASCII-only editors, you may need the following, slightly longer version:
main(c){for(;c=c?c:(c=toupper(getchar())-32)?c<0?1:
"\x95#\x8CKa`^ZRBCEIQiw#S#nx(37+$6-2&#/4)'18=,*%.:0;?5"
[c-12]-34:-3;c/=2)putchar(c/2?46-c%2:32);}
This version is 17 characters longer (weighing in at a comparatively huge 148), due to the following changes:
+4: getchar() and putchar() instead of the non-portable getch() and putch()
+6: escape codes for two of the characters instead of non-ASCII characters
+1: 32 instead of 0 for space character
+6: added "c<0?1:" to suppress garbage from characters less than ASCII 32 (namely, from '\n'). You'll still get garbage from any of !"#$%&'()*+[\]^_`{|}~, or anything above ASCII 126.
This should make the code completely portable. Compile with:
gcc -std=c89 -funsigned-char morse.c
The -std=c89 is optional. The -funsigned-char is necessary, though, or you will get garbage for comma and full stop.
135 characters
c;main(){while(c=toupper(getch()))for(c=c-32?
"•ƒŒKa`^ZRBCEIQiw#S#nx(37+$6-2&#/4)'18=,*%.:0;?5"
[c-44]-34:-3;c;c/=2)putch(c/2?46-c%2:0);}
In my opinion, this latest version is much more visually appealing, too. And no, it's not portable, and it's no longer protected against out-of-bounds input. It also has a pretty bad UI, taking character-by-character input and converting it to Morse Code and having no exit condition (you have to hit Ctrl+Break). But portable, robust code with a nice UI wasn't a requirement.
A brief-as-possible explanation of the code follows:
main(c){
while(c = toupper(getch())) /* well, *sort of* an exit condition */
for(c =
c - 32 ? // effectively: "if not space character"
"•ƒŒKa`^ZRBCEIQiw#S#nx(37+$6-2&#/4)'18=,*%.:0;?5"[c - 44] - 34
/* This array contains a binary representation of the Morse Code
* for all characters between comma (ASCII 44) and capital Z.
* The values are offset by 34 to make them all representable
* without escape codes (as long as chars > 127 are allowed).
* See explanation after code for encoding format.
*/
: -3; /* if input char is space, c = -3
* this is chosen because -3 % 2 = -1 (and 46 - -1 = 47)
* and -3 / 2 / 2 = 0 (with integer truncation)
*/
c; /* continue loop while c != 0 */
c /= 2) /* shift down to the next bit */
putch(c / 2 ? /* this will be 0 if we're down to our guard bit */
46 - c % 2 /* We'll end up with 45 (-), 46 (.), or 47 (/).
* It's very convenient that the three characters
* we need for this exercise are all consecutive.
*/
: 0 /* we're at the guard bit, output blank space */
);
}
Each character in the long string in the code contains the encoded Morse Code for one text character. Each bit of the encoded character represents either a dash or a dot. A one represents a dash, and a zero represents a dot. The least significant bit represents the first dash or dot in the Morse Code. A final "guard" bit determines the length of the code. That is, the highest one bit in each encoded character represents end-of-code and is not printed. Without this guard bit, characters with trailing dots couldn't be printed correctly.
For instance, the letter 'L' is ".-.." in Morse Code. To represent this in binary, we need a 0, a 1, and two more 0s, starting with the least significant bit: 0010. Tack one more 1 on for a guard bit, and we have our encoded Morse Code: 10010, or decimal 18. Add the +34 offset to get 52, which is the ASCII value of the character '4'. So the encoded character array has a '4' as the 33rd character (index 32).
This technique is similar to that used to encode characters in ACoolie's, strager's(2), Miles's, pingw33n's, Alec's, and Andrea's solutions, but is slightly simpler, requiring only one operation per bit (shifting/dividing), rather than two (shifting/dividing and decrementing).
EDIT:
Reading through the rest of the implementations, I see that Alec and Anon came up with this encoding scheme—using the guard bit—before I did. Anon's solution is particularly interesting, using Python's bin function and stripping off the "0b" prefix and the guard bit with [3:], rather than looping, anding, and shifting, as Alec and I did.
As a bonus, this version also handles hyphen (-....-), slash (-..-.), colon (---...), semicolon (-.-.-.), equals (-...-), and at sign (.--.-.). As long as 8-bit characters are allowed, these characters require no extra code bytes to support. No more characters can be supported with this version without adding length to the code (unless there's Morse Codes for greater/less than signs).
Because I find the old implementations still interesting, and the text has some caveats applicable to this version, I've left the previous content of this post below.
Okay, presumably, the user interface can suck, right? So, borrowing from strager, I've replaced gets(), which provides buffered, echoed line input, with getch(), which provides unbuffered, unechoed character input. This means that every character you type gets translated immediately into Morse Code on the screen. Maybe that's cool. It no longer works with either stdin or a command-line argument, but it's pretty damn small.
I've kept the old code below, though, for reference. Here's the new.
New code, with bounds checking, 171 characters:
W(i){i?W(--i/2),putch(46-i%2):0;}c;main(){while(c=toupper(getch())-13)
c=c-19?c>77|c<31?0:W("œ*~*hXPLJIYaeg*****u*.AC5+;79-#6=0/8?F31,2:4BDE"
[c-31]-42):putch(47),putch(0);}
Enter breaks the loop and exits the program.
New code, without bounds checking, 159 characters:
W(i){i?W(--i/2),putch(46-i%2):0;}c;main(){while(c=toupper(getch())-13)
c=c-19?W("œ*~*hXPLJIYaeg*****u*.AC5+;79-#6=0/8?F31,2:4BDE"[c-31]-42):
putch(47),putch(0);}
Below follows the old 196/177 code, with some explanation:
W(i){i?W(--i/2),putch(46-i%2):0;}main(){char*p,c,s[99];gets(s);
for(p=s;*p;)c=*p++,c=toupper(c),c=c-32?c>90|c<44?0:W(
"œ*~*hXPLJIYaeg*****u*.AC5+;79-#6=0/8?F31,2:4BDE"[c-44]-42):
putch(47),putch(0);}
This is based on Andrea's Python answer, using the same technique for generating the morse code as in that answer. But instead of storing the encodable characters one after another and finding their indexes, I stored the indexes one after another and look them up by character (similarly to my earlier answer). This prevents the long gaps near the end that caused problems for earlier implementors.
As before, I've used a character that's greater than 127. Converting it to ASCII-only adds 3 characters. The first character of the long string must be replaced with \x9C. The offset is necessary this time, otherwise a large number of characters are under 32, and must be represented with escape codes.
Also as before, processing a command-line argument instead of stdin adds 2 characters, and using a real space character between codes adds 1 character.
On the other hand, some of the other routines here don't deal with input outside the accepted range of [ ,.0-9\?A-Za-z]. If such handling were removed from this routine, then 19 characters could be removed, bringing the total down as low as 177 characters. But if this is done, and invalid input is fed to this program, it may crash and burn.
The code in this case could be:
W(i){i?W(--i/2),putch(46-i%2):0;}main(){char*p,s[99];gets(s);
for(p=s;*p;p++)*p=*p-32?W(
"œ*~*hXPLJIYaeg*****u*.AC5+;79-#6=0/8?F31,2:4BDE"
[toupper(*p)-44]-42):putch(47),putch(0);}
Using a Morse Code Font?
Console.Write(params[0]);
Perl, 170 characters (with a little help from accomplished golfer mauke). Wrapped for clarity; all newlines are removable.
$_=uc<>;y,. ,|/,;s/./$& /g;#m{A..Z,0..9,qw(| , ?)}=
".-NINNN..]IN-NII..AMN-AI---.M-ANMAA.I.-].AIAA-NANMMIOMAOUMSMSAH.B.MSOIONARZMIZ"
=~/../g;1while s![]\w|,?]!$m{$&}!;print
Explanation:
Extract the morse dictionary. Each symbol is defined in terms of two chars, which can be either literal dots or dashes, or a reference to the value of another defined char. E and T contain dummy chars to avoid desyncing the decoder; we'll remove them later.
Read and format the input. "Hello world" becomes "H E L L O / W O R L D"
The next step depends on the input and output dictionaries being distinct, so turn dots in the input to an unused char (vertical bar, |)
Replace any char in the input that occurs in the morse dictionary with its value in the dictionary, until no replacements occur.
Remove the dummy char mentioned in step 1.
Print the output.
In the final version, the dictionary is optimized for runtime efficiency:
All one-symbol characters (E and T) and two-symbol characters (A, I, M, and N) are defined directly and decode in one pass.
All three-symbol characters are defined in terms of a two-symbol character and a literal symbol, decoding in two passes.
All four-symbol characters are defined in terms of two two-symbol characters, decoding in two passes with three replacements.
The five- and six-symbol characters (numbers and punctuation) decode in three passes, with four or five replacements respectively.
Since the golfed code only replaces one character per loop (to save one character of code!) the number of loops is limited to five times the length of the input (three times the length of the input if only alphabetics are used). But by adding a g to the s/// operation, the number of loops is limited to three (two if only alphabetics are used).
Example transformation:
Hello 123
H E L L O / 1 2 3
II .] AI AI M- / AO UM SM
.... . .-.. .-.. --- / .-M- .A-- I.--
.... . .-.. .-.. --- / .---- ..--- ...--
Python list comprehension, 159-character one-liner
for c in raw_input().upper():print c<","and"/"or bin(ord("•ƒwTaQIECBRZ^`šŒ#S#n|':<.$402&9/6)(18?,*%+3-;=>"[ord(c)-44])-34)[3:].translate(" "*47+"/.-"+" "*206),
Uses the similar data packing to P Daddy's C implementation, but does not store the bits in reverse order and uses bin() to extract the data rather than arithmetic. Note also that spaces are detected using inequality; it considers every character "less than comma" to be a space.
Python for loop, 205 chars including newlines
for a in raw_input().upper():
q='_ETIANMSURWDKGOHVF_L_PJBXCYZQ__54_3___2__+____16=/_____7___8_90'.find(a);s=''
while q>0:s='-.'[q%2]+s;q=~-q/2
print['/','--..--','..--..','.-.-.-',''][' ,?.'.find(a)]+s,
I was dorking around with a compact coding for the symbols, but I don't see if getting any better than the implicit trees already in use, so I present the coding here in case some one else can use it.
Consider the string:
--..--..-.-.-..--...----.....-----.--/
which contains all the needed sequences as substrings. We could code the symbols by offset and length like this:
ET RRRIIGGGJJJJ
--..--..-.-.-..--...----.....-----.--/
CCCC DD WWW 00000
,,,,,, AALLLL BBBB 11111
--..--..-.-.-..--...----.....-----.--/
?????? KKK MMSSS 22222
FFFF PPPP 33333
--..--..-.-.-..--...----.....-----.--/
UUU XXXX 44444
NN PPPP OOO 55555
--..--..-.-.-..--...----.....-----.--/
ZZZZ 66666
77777 YYYY
--..--..-.-.-..--...----.....-----.--/
...... 88888 HHHH
99999 VVVV QQQQ
--..--..-.-.-..--...----.....-----.--/
with the space (i.e. word boundary) starting and ending on the final character (the '/'). Feel free to use it, if you see a good way.
Most of the shorter symbols have several possible codings, of course.
P Daddy found a shorter version of this trick (and I can now see at least some of the redundancy here) and did a nice c implementation. Alec did a python implementation with the first (buggy and incomplete) version. Hobbs did a pretty compact perl version that I don't understand at all.
J, 124 130 134 characters
'.- /'{~;2,~&.>(]`(<&3:)#.(a:=])"0)}.&,&#:&.></.40-~a.i.')}ggWOKIHX`dfggggggg-#B4*:68,?5</.7>E20+193ACD'{~0>.45-~a.i.toupper
J beats C! Awesome!
Usage:
'.- /'{~;2,~&.>(]`(<&3:)#.(a:=])"0)}.&,&#:&.></.40-~a.i.')}ggWOKIHX`dfggggggg-#B4*:68,?5</.7>E20+193ACD'{~0>.45-~a.i.toupper 'Hello World'
.... . .-.. .-.. --- / .-- --- .-. .-.. -..
'.- /'{~;2,~&.>(]`(<&3:)#.(a:=])"0)}.&,&#:&.></.40-~a.i.')}ggWOKIHX`dfggggggg-#B4*:68,?5</.7>E20+193ACD'{~0>.45-~a.i.toupper 'Hello, Stackoverflow.'
.... . .-.. .-.. --- .-.-.- / ... - .- -.-. -.- --- ...- . .-. ..-. .-.. --- .-- --..--
Python 3 One Liner: 172 characters
print(' '.join('/'if c==' 'else''.join('.'if x=='0'else'-'for x in bin(ord("ijÁĕÁÿïçãáàðøüþÁÁÁÁÁČÁÅ×ÚÌÂÒÎÐÄ×ÍÔÇÆÏÖÝÊÈÃÉÑËÙÛÜ"[ord(c)-44])-192)[3:])for c in input().upper()))
(Encoding the tranlation table into unicode code points. Works fine, and they display here fine in my test on my Windows Vista machine.)
Edited to pare down to 184 characters by removing some unnecessary spaces and brackets (making list comps gen exps).
Edit again: More spaces removed that I didn't even know was possible before seeing other answers here - so down to 176.
Edit again down to 172 (woo woo!) by using ' '.join instead of ''.join and doing the spaces separately. (duh!)
C# 266 chars
The 131 char C solution translated to C# yields 266 characters:
foreach(var i in Encoding.ASCII.GetBytes(args[0].ToUpper())){var c=(int)i;for(c=(c-32!=0)?Encoding.ASCII.GetBytes("•ƒŒKa`^ZRBCEIQiw#S#nx(37+$6-2&#/4)'18=,*%.:0;?5")[c-44]-34:-3;c!=0;c/=2)Console.Write(Encoding.ASCII.GetChars(new byte[]{(byte)((c/2!=0)?46-c%2:0)}));}
which is more readable as:
foreach (var i in Encoding.ASCII.GetBytes(args[0].ToUpper()))
{
var c = (int)i;
for (c = ((c - 32) != 0) ? Encoding.ASCII.GetBytes("•ƒŒKa`^ZRBCEIQiw#S#nx(37+$6-2&#/4)'18=,*%.:0;?5")[c - 44] - 34 : -3
; c != 0
; c /= 2)
Console.Write(Encoding.ASCII.GetChars(new byte[] { (byte)((c / 2 != 0) ? 46 - c % 2 : 0) }));
}
Golfscript - 106 chars - NO FUNNY CHARS :)
newline at the end of the input is not supported, so use something like this
echo -n Hello, Stackoverflow| ../golfscript.rb morse.gs
' '/{{.32|"!etianmsurwdkgohvf!l!pjbxcyzq"?)"UsL?/'#! 08<>"#".,?0123456789"?=or
2base(;>{'.-'\=}%' '}%}%'/'*
Letters are a special case and converted to lowercase and ordered in their binary positions.
Everything else is done by a translation table
Python
Incomplete solution, but maybe somebody can make a full solution out of it. Doesn't handle digits or punctuation, but weighs in at only 154 chars.
def e(l):
i='_etianmsurwdkgohvf_l_pjbxcyzq'.find(l.lower());v=''
while i>0:v='-.'[i%2]+v;i=(i-1)/2;return v or '/'
def enc(s):return ' '.join(map(e,s))
C (248 characters)
Another tree-based solution.
#define O putchar
char z[99],*t=
" ETINAMSDRGUKWOHBL~FCPJVX~YZQ~~54~3~~~2~~+~~~~16=/~~.~~7,~~8~90";c,p,i=0;
main(){gets(z);while(c=z[i++]){c-46?c-44?c:O(45):O(c);c=c>96?c-32:c;p=-1;
while(t[++p]!=c);for(;p;p/=2){O(45+p--%2);}c-32?O(32):(O(47),O(c));}}
Could be errors in source tree because wikipedia seems to have it wrong or maybe I misunderstood something.
F#, 256 chars
let rec D i=if i=16 then" "else
let x=int"U*:+F8c]uWjGbJ0-0Dnmd0BiC5?\4o`h7f>9[1E=pr_".[i]-32
if x>43 then"-"+D(x-43)else"."+D x
let M(s:string)=s.ToUpper()|>Seq.fold(fun s c->s+match c with
|' '->"/ "|','->"--..-- "|'.'->".-.-.- "|_->D(int c-48))""
For example
M("Hello, Stack.") |> printfn "%s"
yields
.... . .-.. .-.. --- --..-- / ... - .- -.-. -.- .-.-.-
I think my technique may be unique so far. The idea is:
there is an ascii range of chars that covers most of what we want (0..Z)
there are only 43 chars in this range
thus we can encode one bit (dash or dot) plus a 'next character' in a range of 86 chars
the range ascii(32-117) is all 'printable' and can serve as this 86-char range
so the string literal encodes a table along those lines
There's a little more to it, but that's the gist. Comma, period, and space are not in the range 0..Z so they're handled specially by the 'match'. Some 'unused' characters in the range 0..Z (like ';') are used in the table as suffixes of other morse translations that aren't themselves morse 'letters'.
Here's my contribution as a console application in VB.Net
Module MorseCodeConverter
Dim M() As String = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----."}
Sub Main()
Dim I, O
Dim a, b
While True
I = Console.ReadLine()
O = ""
For Each a In I
b = AscW(UCase(a))
If b > 64 And b < 91 Then
O &= M(b - 65) & " "
ElseIf b > 47 And b < 58 Then
O &= M(b - 22) & " "
ElseIf b = 46 Then
O &= ".-.-.- "
ElseIf b = 44 Then
O &= "--..-- "
ElseIf b = 63 Then
O &= "..--.. "
Else
O &= "/"
End If
Next
Console.WriteLine(O)
End While
End Sub
End Module
I left he white space in to make it readable. Totals 1100 characters. It will read the input from the command line, one line at a time, and send the corresponding output back to the output stream. The compressed version is below, with only 632 characters.
Module Q
Dim M() As String={".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----."}
Sub Main()
Dim I,O,a,b:While 1:I=Console.ReadLine():O="":For Each a In I:b=AscW(UCase(a)):If b>64 And b<91 Then:O &=M(b-65)&" ":ElseIf b>47 And b<58 Then:O &=M(b-22)&" ":ElseIf b=46 Then:O &=".-.-.- ":ElseIf b=44 Then:O &="--..-- ":ElseIf b=63 Then:O &= "..--.. ":Else:O &="/":End IF:Next:Console.WriteLine(O):End While
End Sub
End Module
C (233 characters)
W(n,p){while(n--)putch(".-.-.--.--..--..-.....-----..../"[p++]);}main(){
char*p,c,s[99];gets(s);for(p=s;*p;){c=*p++;c=toupper(c);c=c>90?35:c-32?
"È#À#¶µ´³²±°¹¸·#####Ê##i Že‘J•aEAv„…`q!j“d‰ƒˆ"[c-44]:63;c-35?
W(c>>5,c&31):0;putch(0);}}
This takes input from stdin. Taking input from the command line adds 2 characters. Instead of:
...main(){char*p,c,s[99];gets(s);for(p=s;...
you get:
...main(int i,char**s){char*p,c;for(p=s[1];...
I'm using Windows-1252 code page for characters above 127, and I'm not sure how they'll turn up in other people's browsers. I notice that, in my browser at least (Google Chrome), two of the characters (between "#" and "i") aren't showing up. If you copy out of the browser and paste into a text editor, though, they do show up, albeit as little boxes.
It can be converted to ASCII-only, but this adds 24 characters, increasing the character count to 257. To do this, I first offset each character in the string by -64, minimizing the number of characters that are greater than 127. Then I substitute \xXX character escapes where necessary. It changes this:
...c>90?35:c-32?"È#À#¶µ´³²±°¹¸·#####Ê##i Že‘J•aEAv„…`q!j“d‰ƒˆ"[c-44]:63;
c-35?W(...
to this:
...c>90?99:c-32?"\x88#\x80#vutsrqpyxw#####\x8A#\0PA)\xE0N%Q\nU!O\5\1\66DE 1
\xE1*S$ICH"[c-44]+64:63;c-99?W(...
Here's a more nicely formatted and commented version of the code:
/* writes `n` characters from internal string to stdout, starting with
* index `p` */
W(n,p){
while(n--)
/* warning for using putch without declaring it */
putch(".-.-.--.--..--..-.....-----..../"[p++]);
/* dmckee noticed (http://tinyurl.com/n4eart) the overlap of the
* various morse codes and created a 37-character-length string that
* contained the morse code for every required character (except for
* space). You just have to know the start index and length of each
* one. With the same idea, I came up with this 32-character-length
* string. This not only saves 5 characters here, but means that I
* can encode the start indexes with only 5 bits below.
*
* The start and length of each character are as follows:
*
* A: 0,2 K: 1,3 U: 10,3 4: 18,5
* B: 16,4 L: 15,4 V: 19,4 5: 17,5
* C: 1,4 M: 5,2 W: 4,3 6: 16,5
* D: 9,3 N: 1,2 X: 9,4 7: 25,5
* E: 0,1 O: 22,3 Y: 3,4 8: 24,5
* F: 14,4 P: 4,4 Z: 8,4 9: 23,5
* G: 5,3 Q: 5,4 0: 22,5 .: 0,6
* H: 17,4 R: 0,3 1: 21,5 ,: 8,6
* I: 20,2 S: 17,3 2: 20,5 ?: 10,6
* J: 21,4 T: 1,1 3: 19,5
*/
}
main(){ /* yuck, but it compiles and runs */
char *p, c, s[99];
/* p is a pointer within the input string */
/* c saves from having to do `*p` all the time */
/* s is the buffer for the input string */
gets(s); /* warning for use without declaring */
for(p=s; *p;){ /* begin with start of input, go till null character */
c = *p++; /* grab *p into c, increment p.
* incrementing p here instead of in the for loop saves
* one character */
c=toupper(c); /* warning for use without declaring */
c = c > 90 ? 35 : c - 32 ?
"È#À#¶µ´³²±°¹¸·#####Ê##i Že‘J•aEAv„…`q!j“d‰ƒˆ"[c - 44] : 63;
/**** OR, for the ASCII version ****/
c = c > 90 ? 99 : c - 32 ?
"\x88#\x80#vutsrqpyxw#####\x8A#\0PA)\xE0N%Q\nU!O\5\1\66DE 1\xE1"
"*S$ICH"[c - 44] + 64 : 63;
/* Here's where it gets hairy.
*
* What I've done is encode the (start,length) values listed in the
* comment in the W function into one byte per character. The start
* index is encoded in the low 5 bits, and the length is encoded in
* the high 3 bits, so encoded_char = (char)(length << 5 | position).
* For the longer, ASCII-only version, 64 is subtracted from the
* encoded byte to reduce the necessity of costly \xXX representations.
*
* The character array includes encoded bytes covering the entire range
* of characters covered by the challenge, except for the space
* character, which is checked for separately. The covered range
* starts with comma, and ends with capital Z (the call to `toupper`
* above handles lowercase letters). Any characters not supported are
* represented by the "#" character, which is otherwise unused and is
* explicitly checked for later. Additionally, an explicit check is
* done here for any character above 'Z', which is changed to the
* equivalent of a "#" character.
*
* The encoded byte is retrieved from this array using the value of
* the current character minus 44 (since the first supported character
* is ASCII 44 and index 0 in the array). Finally, for the ASCII-only
* version, the offset of 64 is added back in.
*/
c - 35 ? W(c >> 5, c & 31) : 0;
/**** OR, for the ASCII version ****/
c - 99 ? W(c >> 5, c & 31) : 0;
/* Here's that explicit check for the "#" character, which, as
* mentioned above, is for characters which will be ignored, because
* they aren't supported. If c is 35 (or 99 for the ASCII version),
* then the expression before the ? evaluates to 0, or false, so the
* expression after the : is evaluated. Otherwise, the expression
* before the ? is non-zero, thus true, so the expression before
* the : is evaluated.
*
* This is equivalent to:
*
* if(c != 35) // or 99, for the ASCII version
* W(c >> 5, c & 31);
*
* but is shorter by 2 characters.
*/
putch(0);
/* This will output to the screen a blank space. Technically, it's not
* the same as a space character, but it looks like one, so I think I
* can get away with it. If a real space character is desired, this
* must be changed to `putch(32);`, which adds one character to the
* overall length.
} /* end for loop, continue with the rest of the input string */
} /* end main */
This beats everything here except for a couple of the Python implementations. I keep thinking that it can't get any shorter, but then I find some way to shave off a few more characters. If anybody can find any more room for improvement, let me know.
EDIT:
I noticed that, although this routine rejects any invalid characters above ASCII 44 (outputting just a blank space for each one), it doesn't check for invalid characters below this value. To check for these adds 5 characters to the overall length, changing this:
...c>90?35:c-32?"...
to this:
...c-32?c>90|c<44?35:"...
REBOL (118 characters)
A roughly 10 year-old implementation
foreach c ask""[l: index? find" etinamsdrgukwohblzfcpövxäqüyj"c while[l >= 2][prin pick"-."odd? l l: l / 2]prin" "]
Quoted from: http://www.rebol.com/oneliners.html
(no digits though and words are just separated by double spaces :/ ...)
Python (210 characters)
This is a complete solution based on Alec's one
def e(l):
i=(' etianmsurwdkgohvf_l_pjbxcyzq__54_3___2%7s16%7s7___8_90%12s?%8s.%29s,'%tuple('_'*5)).find(l.lower());v=''
while i>0:v='-.'[i%2]+v;i=(i-1)/2
return v or '/'
def enc(s):return ' '.join(map(e,s))
C, 338 chars
338 with indentation and all removable linebreaks removed:
#define O putchar
#define W while
char*l="x#####ppmmmmm##FBdYcbcbSd[Kcd`\31(\b1g_<qCN:_'|\25D$W[QH0";
int c,b,o;
main(){
W(1){
W(c<32)
c=getchar()&127;
W(c>96)
c^=32;
c-=32;
o=l[c/2]-64;
b=203+(c&1?o>>3:0);
o=c&1?o&7:o>>3;
W(o>6)
O(47),o=0;
c/=2;
W(c--)
b+=(l[c]-64&7)+(l[c]-64>>3);
b=(((l[b/7]<<7)+l[b/7+1])<<(b%7))>>14-o;
W(o--)
O(b&(1<<o)?46:45);
O(32);
}
}
This isn't based on the tree approach other people have been taking. Instead, l first encodes the lengths of all bytes between 32 and 95 inclusive, two bytes to a character. As an example, D is -.. for a length of 3 and E is . for a length of 1. This is encoded as 011 and 001, giving 011001. To make more characters encodable and avoid escapes, 64 is then added to the total, giving 1011001 - 89, ASCII Y. Non-morse characters are assigned a length of 0. The second half of l (starting with \031) are the bits of the morse code itself, with a dot being 1 and a dash 0. To avoid going into high ASCII, this data is encoded 7 bits/byte.
The code first sanitises c, then works out the morse length of c (in o), then adds up the lengths of all the previous characters to produce b, the bit index into the data.
Finally, it loops through the bits, printing dots and dashes.
The length '7' is used as a special flag for printing a / when encountering a space.
There are probably some small gains to be had from removing brackets, but I'm way off from some of the better results and I'm hungry, so...
C# Using Linq (133 chars)
static void Main()
{
Console.WriteLine(String.Join(" ", (from c in Console.ReadLine().ToUpper().ToCharArray()
select m[c]).ToArray()));
}
OK, so I cheated. You also need to define a dictionary as follows (didn't bother counting the chars, since this blows me out of the game):
static Dictionary<char, string> m = new Dictionary<char, string>() {
{'A', ".-"},
{'B', "-.."},
{'C', "-.-."},
{'D', "-.."},
{'E', "."},
{'F', "..-."},
{'G', "--."},
{'H', "...."},
{'I', ".."},
{'J', ".---"},
{'K', "-.-"},
{'L', ".-.."},
{'M', "--"},
{'N', "-."},
{'O', "---"},
{'P', ".--."},
{'Q', "--.-"},
{'R', ".-."},
{'S', "..."},
{'T', "-"},
{'U', "..-"},
{'V', "...-"},
{'W', ".--"},
{'X', "-..-"},
{'Y', "-.--"},
{'Z', "--.."},
{'0', "-----"},
{'1', ".----"},
{'2', "..---"},
{'3', "...--"},
{'4', "....-"},
{'5', "....."},
{'6', "-...."},
{'7', "--..."},
{'8', "---.."},
{'9', "----."},
{' ', "/"},
{'.', ".-.-.-"},
{',', "--..--"},
{'?', "..--.."},
};
Still, can someone provide a more concise C# implementation which is also as easy to understand and maintain as this?
Perl, 206 characters, using dmckee's idea
This is longer than the first one I submitted, but I still think it's interesting. And/or awful. I'm not sure yet. This makes use of dmckee's coding idea, plus a couple other good ideas that I saw around. Initially I thought that the "length/offset in a fixed string" thing couldn't come out to less data than the scheme in my other solution, which uses a fixed two bytes per char (and all printable bytes, at that). I did in fact manage to get the data down to considerably less (one byte per char, plus four bytes to store the 26-bit pattern we're indexing into) but the code to get it out again is longer, despite my best efforts to golf it. (Less complex, IMO, but longer anyway).
Anyway, 206 characters; newlines are removable except the first.
#!perl -lp
($a,#b)=unpack"b32C*",
"\264\202\317\0\31SF1\2I.T\33N/G\27\308XE0=\x002V7HMRfermlkjihgx\207\205";
$a=~y/01/-./;#m{A..Z,0..9,qw(. , ?)}=map{substr$a,$_%23,1+$_/23}#b;
$_=join' ',map$m{uc$_}||"/",/./g
Explanation:
There are two parts to the data. The first four bytes ("\264\202\317\0") represent 32 bits of morse code ("--.-..-.-.-----.....--..--------") although only the first 26 bits are used. This is the "reference string".
The remainder of the data string stores the starting position and length of substrings of the reference string that represent each character -- one byte per character, in the order (A, B, ... Z, 0, 1, ... 9, ".", ",", "?"). The values are coded as 23 * (length - 1) + pos, and the decoder reverses that. The last starting pos is of course 22.
So the unpack does half the work of extracting the data and the third line (as viewed here) does the rest, now we have a hash with $m{'a'} = '.-' et cetera, so all there is left is to match characters of the input, look them up in the hash, and format the output, which the last line does... with some help from the shebang, which tells perl to remove the newline on input, put lines of input in $_, and when the code completes running, write $_ back to output with newlines added again.
Python 2; 171 characters
Basically the same as Andrea's solution, but as a complete program, and using stupid tricks to make it shorter.
for c in raw_input().lower():print"".join(".-"[int(d)]for d in bin(
(' etianmsurwdkgohvf_l_pjbxcyzq__54_3___2%7s16%7s7___8_90%12s?%8s.%29s,'
%(('',)*5)).find(c))[3:])or'/',
(the added newlines can all be removed)
Or, if you prefer not to use the bin() function in 2.6, we can get do it in 176:
for c in raw_input():C=lambda q:q>0and C(~-q/2)+'-.'[q%2]or'';print C(
(' etianmsurwdkgohvf_l_pjbxcyzq__54_3___2%7s16%7s7___8_90%12s?%8s.%29s,'%
(('',)*5)).find(c.lower()))or'/',
(again, the added newlines can all be removed)
C89 (293 characters)
Based off some of the other answers.
EDIT: Shrunk the tree (yay).
#define P putchar
char t['~']="~ETIANMSURWDKGOHVF~L~PJBXCYZQ~~54~3",o,q[9],Q=10;main(c){for(;Q;)t[
"&./7;=>KTr"[--Q]]="2167890?.,"[Q];while((c=getchar())>=0){c-=c<'{'&c>96?32:0;c-
10?c-32?0:P(47):P(10);for(o=1;o<'~';++o)if(t[o]==c){for(;o;o/=2)q[Q++]=45+(o--&1
);for(;Q;P(q[--Q]));break;}P(32);}}
Here's another approach, based on dmckee's work, demonstrating just how readable Python is:
Python
244 characters
def h(l):p=2*ord(l.upper())-88;a,n=map(ord,"AF__GF__]E\\E[EZEYEXEWEVEUETE__________CF__IBPDJDPBGAHDPC[DNBSDJCKDOBJBTCND`DKCQCHAHCZDSCLD??OD"[p:p+2]);return "--..--..-.-.-..--...----.....-----.-"[a-64:a+n-128]
def e(s):return ' '.join(map(h,s))
Limitations:
dmckee's string missed the 'Y' character, and I was too lazy to add it. I think you'd just have to change the "??" part, and add a "-" at the end of the second string literal
it doesn't put '/' between words; again, lazy
Since the rules called for fewest characters, not fewest bytes, you could make at least one of my lookup tables smaller (by half) if you were willing to go outside the printable ASCII characters.
EDIT: If I use naïvely-chosen Unicode chars but just keep them in escaped ASCII in the source file, it still gets a tad shorter because the decoder is simpler:
Python
240 characters
def h(l):a,n=divmod(ord(u'\x06_7_\xd0\xc9\xc2\xbb\xb4\xad\xa6\x9f\x98\x91_____\x14_AtJr2<s\xc1d\x89IQdH\x8ff\xe4Pz9;\xba\x88X_f'[ord(l.upper())-44]),7);return "--..--..-.-.-..--...----.....-----.-"[a:a+n]
def e(s):return ' '.join(map(h,s))
I think it also makes the intent of the program much clearer.
If you saved this as UTF-8, I believe the program would be down to 185 characters, making it the shortest complete Python solution, and second only to Perl. :-)
Here's a third, completely different way of encoding morse code:
Python
232 characters
def d(c):
o='';b=ord("Y_j_?><80 !#'/_____f_\x06\x11\x15\x05\x02\x15\t\x1c\x06\x1e\r\x12\x07\x05\x0f\x16\x1b\n\x08\x03\r\x18\x0e\x19\x01\x13"[ord(c.upper())-44])
while b!=1:o+='.-'[b&1];b/=2
return o
e=lambda s:' '.join(map(d,s))
If you can figure out a way to map this onto some set of printable characters, you could save quite a few characters. This is probably my most direct solution, though I don't know if it's the most readable.
OK, now I've wasted way too much time on this.
Haskell
type MorseCode = String
program :: String
program = "__5__4H___3VS__F___2 UI__L__+_ R__P___1JWAE"
++ "__6__=B__/_XD__C__YKN__7_Z__QG__8_ __9__0 OMT "
decode :: MorseCode -> String
decode = interpret program
where
interpret = head . foldl exec []
exec xs '_' = undefined : xs
exec (x:y:xs) c = branch : xs
where
branch (' ':ds) = c : decode ds
branch ('-':ds) = x ds
branch ('.':ds) = y ds
branch [] = [c]
For example, decode "-- --- .-. ... . -.-. --- -.. ." returns "MORSE CODE".
This program is from taken from the excellent article Fun with Morse Code.
PHP
I modified the previous PHP entry to be slightly more efficient. :)
$a=array(32=>"/",44=>"--..--",1,".-.-.-",48=>"-----",".----","..---","...--","....-",".....","-....","--...","---..","----.",63=>"..--..",1,".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..");
foreach(str_split(strtoupper("hello world?"))as$k=>$v){echo $a[ord($v)]." ";}
Komodo says 380 characters on 2 lines - the extra line is just for readability. ;D
The interspersed 1s in the array is just to save 2 bytes by filling that array position with data instead of manually jumping to the array position after that.
Consider the first vs. the second. The difference is clearly visible. :)
array(20=>"data",22=>"more data";
array(20=>"data",1,"more data";
The end result, however, is exactly as long as you use the array positions rather than loop through the contents, which we don't do on this golf course.
End result: 578 characters, down to 380 (198 characters, or ~34.26% savings).
Bash, a script I wrote a while ago (time-stamp says last year) weighing in at a hefty 1661 characters. Just for fun really :)
#!/bin/sh
txt=''
res=''
if [ "$1" == '' ]; then
read -se txt
else
txt="$1"
fi;
len=$(echo "$txt" | wc -c)
k=1
while [ "$k" -lt "$len" ]; do
case "$(expr substr "$txt" $k 1 | tr '[:upper:]' '[:lower:]')" in
'e') res="$res"'.' ;;
't') res="$res"'-' ;;
'i') res="$res"'..' ;;
'a') res="$res"'.-' ;;
'n') res="$res"'-.' ;;
'm') res="$res"'--' ;;
's') res="$res"'...' ;;
'u') res="$res"'..-' ;;
'r') res="$res"'.-.' ;;
'w') res="$res"'.--' ;;
'd') res="$res"'-..' ;;
'k') res="$res"'-.-' ;;
'g') res="$res"'--.' ;;
'o') res="$res"'---' ;;
'h') res="$res"'....' ;;
'v') res="$res"'...-' ;;
'f') res="$res"'..-.' ;;
'l') res="$res"'.-..' ;;
'p') res="$res"'.--.' ;;
'j') res="$res"'.---' ;;
'b') res="$res"'-...' ;;
'x') res="$res"'-..-' ;;
'c') res="$res"'-.-.' ;;
'y') res="$res"'-.--' ;;
'z') res="$res"'--..' ;;
'q') res="$res"'--.-' ;;
'5') res="$res"'.....' ;;
'4') res="$res"'....-' ;;
'3') res="$res"'...--' ;;
'2') res="$res"'..---' ;;
'1') res="$res"'.----' ;;
'6') res="$res"'-....' ;;
'7') res="$res"'--...' ;;
'8') res="$res"'---..' ;;
'9') res="$res"'----.' ;;
'0') res="$res"'-----' ;;
esac;
[ ! "$(expr substr "$txt" $k 1)" == " " ] && [ ! "$(expr substr "$txt" $(($k+1)) 1)" == ' ' ] && res="$res"' '
k=$(($k+1))
done;
echo "$res"
C89 (388 characters)
This is incomplete as it doesn't handle comma, fullstop, and query yet.
#define P putchar
char q[10],Q,tree[]=
"EISH54V 3UF 2ARL + WP J 1TNDB6=X/ KC Y MGZ7 Q O 8 90";s2;e(x){q[Q++]
=x;}p(){for(;Q--;putchar(q[Q]));Q=0;}T(int x,char*t,int s){s2=s/2;return s?*t-x
?t[s2]-x?T(x,++t+s2,--s/2)?e(45):T(x,t,--s/2)?e(46):0:e(45):e(46):0;}main(c){
while((c=getchar())>=0){c-=c<123&&c>96?32:0;if(c==10)P(10);if(c==32)P(47);else
T(c,tree,sizeof(tree)),p();P(' ');}}
Wrapped for readability. Only two of the linebreaks are required (one for the #define, one after else, which could be a space). I've added a few non-standard characters but didn't add non-7-bit ones.
C, 533 characters
I took advice from some comments and switched to stdin. Killed another 70 characters roughly.
#include <stdio.h>
#include <ctype.h>
char *u[36] = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----."};
main(){
char*v;int x;char o;
do{
o = toupper(getc(stdin));v=0;if(o>=65&&o<=90)v=u[o-'A'];if(o>=48&&o<=57)v=u[o-'0'+26];if(o==46)v=".-.-.-";if(o==44)v="--..--";if(o==63)v="..--..";if(o==32)v="/";if(v)printf("%s ", v);} while (o != EOF);
}
C (381 characters)
char*p[36]={".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----."};
main(){int c;while((c=tolower(getchar()))!=10)printf("%s ",c==46?".-.-.-":c==44?"--..--":c==63?"..--..":c==32?"/":*(p+(c-97)));}
C, 448 bytes using cmdline arguments:
char*a[]={".-.-.-","--..--","..--..","/",".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----."},*k=".,? ",*s,*p,x;main(int _,char**v){for(;s=*++v;putchar(10))for(;x=*s++;){p=strchr(k,x);printf("%s ",p?a[p-k]:isdigit(x)?a[x-18]:isalpha(x=toupper(x))?a[x-61]:0);}}
C, 416 bytes using stdin:
char*a[]={".-.-.-","--..--","..--..","/",".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..","-----",".----","..---","...--","....-",".....","-....","--...","---..","----."},*k=".,? ",*p,x;main(){while((x=toupper(getchar()))-10){p=strchr(k,x);printf("%s ",p?a[p-k]:isdigit(x)?a[x-18]:isalpha(x)?a[x-61]:0);}}