별 찍기
위키책, 위키책
별 찍기 문제는 프로그래밍 입문자에게 제어문과 배열을 접하게 하기 위한 과제로 사용된다. 보통 콘솔 환경에서 순환문을 통해 직접 아스테리스크(*)를 출력하거나 배열을 조작한 후 순환문으로 출력하는 등의 방법이 사용되며, 이 과정을 통해 입문자들은 변수, 제어문 및 배열 등을 직접 다루어보게 된다.
학원이나 대학교에서 신입생을 위한 과제로 출제되며, 일반적으로 기본적인 별 찍기 문제는 다음의 출력을 만들어낼 것을 요구한다.
Result : * ** *** **** *****
위 피라미드형은 가장 간단하고 난이도가 낮은 문제이다. 이 외에는 나비형이나 다이아몬드형 등의 응용 문제들이 있으며 해법도 여러 가지가 존재한다.
신학기에 위 문제를 처음 접하는 많은 대학생들이 프로그래밍 포럼에 찾아가 이 문제에 관한 질문을 올려, 신학기엔 많은 포럼들의 게시물 다수가 별 찍기 질문글들로 채워지곤 한다. 여러 포럼에서는 단순히 문제의 해답만을 요구하는 학생들에 대해서 불성실하다는 이유로 부정적인 입장을 보인다.
프로그래밍 커뮤니티 중 하나인 디시인사이드 프로그래밍 갤러리에서는 "새싹밟기"라는 제목으로 일반적으로는 생각하지 못했던 창의적인 별 찍기, 다이아몬드, 전문 별 찍기 솔루션 등이 올라오는 등 여러 가지 방법의 별 찍기 프로그램을 등록하는 것이 하나의 유행이 되기도 했다.
| 한국어 위키백과에 수록된 별찍기 관련 문서 참고. |
차례 |
[+/-] 별 찍기에 대한 일반적 접근
일반적인 별 찍기 문제에 대한 접근법으로는 아스태리스크(*)를 모니터에 찍을 수 있는 함수와 제어문을 사용하여 모니터 좌측 상단에서 순차적으로 찍어내리는 방법을 사용한다. 이는 일반적으로 출력이 좌측 상단에서부터 시작되기 때문이다. 이에 대한 일반적인 C 언어의 코드는 다음과 같다. 사용자에 따라 일부 코드에 차이가 있을 수 있음을 밝혀둔다.
#include <stdio.h> int main(void) { int i, j; for(i = 0; i < 5; i++) { for(j = 0; j <= i; j++) { putchar ('*'); } putchar('\n'); } return 0; }
그러나 삼각형의 모양이 바뀌어 좌측에 공백이 필요한 경우 일반적으로 " "(공백, 스페이스) 문자를 같이 이용하여 별 찍기 문제를 해결한다. 대표적인 예로는 정삼각형 출력이나 다이아몬드 출력 등이 있다. 이 이외에 별을 화면 중앙이나 그 외 임의의 위치에 출력해야 하는 문제가 존재하기도 한다. 이 경우 일반적으로 출력 커서의 위치를 옮기는 명령을 사용한다. 출력해야 할 도형이 복잡할 경우 - 특히 수학적 도형이나 규칙없는 그림 같은 경우 - 배열을 사용하여 그 정보를 넣은 후 제어문을 통해 배열을 읽어 별을 출력하기도 한다.
이 이외에 별 찍기 문제의 경우 제어문의 심층적 활용이나 아스키 코드의 활용, 재귀함수의 이해 등 여러 분야의 예제로 사용되고 있으며 어떤 경우 디자인 패턴에 관한 예제로 사용되기도 한다.
[+/-] 일반적인 별 찍기
[+/-] 그루비
[+/-] 일반적
(1..5).each { println '*' * it }
[+/-] 웹서비스
GroovySoap 모듈이 필요하다.
서버쪽
StarService.groovy
def getStar() { def result = (1..5).inject('') { str, it -> str += '*' * it + '\n' } }
StarServer.groovy
import groovy.net.soap.SoapServer def server = new SoapServer("localhost", 6980) server.setNode("StarService") server.start()
StarServer를 실행한다.
클라이언트쪽
import groovy.net.soap.SoapClient def proxy = new SoapClient("http://localhost:6980/StarServiceInterface?wsdl") println proxy.getStar()
호스트 IP가 서버쪽을 향하게 만든 후 실행한다.
[+/-] 루비
puts (1..5).map{ |i| "*" * i }.join("\n")
또는
5.times { |i| puts "*" * (i+1) }
또는
(1..5).each{ |i| puts "*"*i}
[+/-] 루아 스크립트
for i = 1, 5 do for j = 1, i do io.write "*" end io.write "\n" end
[+/-] 베이직
For I = 1 To 5 Print String$(I, "*") Next I
[+/-] 본 어게인 셸 스크립트(BASH)
#!/bin/bash for((i=1;i<6;i++)) do for((j=0;j<i;j++)) do echo -n '*' done echo done
또는
#/bin/sh n=5 for i in `seq 1 $n`; do for j in `seq 1 $i`; do echo -n '*' done echo '' done
[+/-] 스몰토크
"Dolphin Smalltalk에서 테스트" i := 0. [i < 5] whileTrue: [ j := 0. [j <= i] whileTrue: [ Transcript show: '*'. j := j + 1 ]. Transcript cr. i := i + 1 ].
[+/-] (좀 더 간단한 버전)
"Squeak에서 테스트" 1 to: 5 do: [ :i | i timesRepeat: [ Transcript show: '*']. Transcript cr. ].
[+/-] 스킴
;(plt scheme 의 개발환경 DrScheme에서 language를 standard(R5RS)로 맞춘후 테스트) (define-syntax when (syntax-rules () ((_ e0 e1 e2 ...) (if e0 (begin e1 e2 ...))))) (define (print-ntimes n s) (when (> n 0) (display s) (print-ntimes (- n 1) s))) (define (star n) (let loop ((i 1)) (when (<= i n) (print-ntimes i "*") (newline) (loop (+ i 1))))) (star 5)
[+/-] 자바
[+/-] (일반적)
package org.wikibooks.ko; public class PrintStarBasic { public static void main(String[] args) { for(int line = 0; line < 5; ++line) { for(int width = 0; width < line + 1; ++width ) { System.out.print("*"); } System.out.println(""); } } }
[+/-] (루프 하나와 문자열 이용)
package org.wikibooks.ko; public class StarPrinter { public static void main(String args[]) { String star ="*****"; for(int i = 0 ; i < star.length() ;i++) { System.out.println(star.substring(0,i+1)); } } }
[+/-] 자바스크립트 (ECMAScript)
XHTML 1.0 표준을 따름
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Printing Star</title> <script type="text/javascript"> /* <![CDATA[ */ var printStar = function() { for(var count = 1; count < 6; ++count) { for(var floor = 0; floor <= count; ++floor) { if(floor == count) { document.write("<br/>"); } else { document.write("*"); } } } }; /* ]]> */</script> </head> <body onload="printStar()"> </body> </html>
[+/-] 파이썬
for i in range(1,6): print "*" * i
[+/-] (한줄)
print "\n".join("*" * i for i in range(1, 6))
[+/-] 펄
[+/-] (일반적)
print "*"x$_."\n" for 1..5
[+/-] (펄 5.10 버전)
say "*"x$_ for 1..5
또는
map{say"*"x$_}1..5
[+/-] (스페셜 버젼)
아래 코드는 모습은 특이하지만 잘 실행된다.
''=~('('."\?".
'{'.('`'|'%').(('[')^
'-').('`'|'!').('`'|(',')).
'"'.'#'.'!'.'/'.('['^'.').("\["^
'(').('['^')').'/'.('`'|'"').("\`"|
')').('`'|'.').'/'.('['^'+').('`'|'%').
('['^')').('`'|',').('!'^'+').('[' ^((
'+'))).('['^')').('`'|')').('`'|'.' ).(
'['^'/').('{'^'[').'\\'.'"'.'*'.'\\' .((
'"')).('['^'#').'\\'.'$'.'_'.'.'.'\\'. '"'.
'\\'.'\\'.('`'|'.').'\\'.'"'.('{'^'[').( "\`"|
'&').('`'|'/').('['^')').('{'^'[').('^'^( ('`')|
'/')).'.'.'.'.('^'^('`'|'+')).('!'^'+').'"'. '}'.')');
$:='.'^'~';$~="\@"| '(';$^=')'^('[');$/=
'`'|'.';$,="\("^ '}';$\='`'|'!';
$:=')'^'}';$~= '*'|"\`";$^=
'+'^"\_";$/= '&'|"\@";
$,='['&'~'; $\=','
^'|';$:='.' ^'~';
$~='@'|'(' ;$^=')'^'[';$/ ='`'|'.';$,='(' ^'}'
;$\="\`"| ( '!');$:= ( ')')^
'}';$~="\*"| ( ( ( ( '`'))));$^='+'^
"\_";$/= ( ( ( ( '&')))
)|'@';$, = (( ( ( ( '[')))
))&"\~"; ( ( ( ( $\))))
=(',')^ '|';$:=('.')^ '~';$~='@'|"\("; $^ =(
')')^ ( ( (
( ( ( ( (
( ( ( (
( ( ( (
( ( ( ( (
( (( '[')) )) )
) ) )
) )
) ) )
) ) )
))))))));( ( ( (
( $/)))))=('`')| (
( '.') );$, = ( (
( ( (( ( (
( ((
( (( '(' )
))))))))))))) ^
( '}');#;#;#; #
;
# ;
#
;
# ;
# ;
# ;
# ;
#;#;#;#;#;#
[+/-] (펄 ppencode)
출처[[1]]
length q bless glob and print chr oct oct oct ord qw q dump q and print chr length q closedir vec and print chr oct oct oct ord qw q dump q and print chr oct oct oct ord qw q dump q and print chr length q continue vec and print chr oct oct oct ord qw q dump q and print chr oct oct oct ord qw q do q and print chr oct oct oct ord qw q dump q and print chr length q binmode glob and print chr oct oct oct ord qw q dump q and print chr oct oct oct ord qw q do q and print chr oct oct oct ord qw q do q and print chr oct oct oct ord qw q do q and print chr length q closedir vec and print chr oct oct oct ord qw q dump q and print chr oct oct oct ord qw q do q and print chr oct oct oct ord qw q do q and print chr oct oct oct ord qw q do q and print chr oct oct oct ord qw q die q and print chr length q closedir vec
[+/-] 포스
: star ( -- ) [char] * emit ;
: stars ( n -- ) 0 ?do star loop ;
: pyramid ( n -- )
cr
0 ?do
i 1 + stars cr
loop
cr
;
5 pyramid
[+/-] C
[+/-] (근성찍기)
#include <stdio.h> int main() { printf("*\n"); printf("**\n"); printf("***\n"); printf("****\n"); printf("*****\n"); return 0; }
[+/-] (문자배열을 포인터로 사용)
#include <stdio.h> #include <string.h> int main() { char stars[] = "-*****"; char* p = stars+strlen(stars)-1; while( *p != '-' ) printf("%s\n", p--); return 0; }
[+/-] (재귀호출 사용)
#include <stdio.h> int PrintStar(int Width,int Height){ int i; for(i=0;i<width;i++){ printf("*"); } printf("\n"); if(Width==Height) return 0; else PrintStar(width+1,Heght); } int main(){ int First_Width=1; int Heghit=5; PrintStar(First_Width,Heghit); return 0; }
[+/-] C++
[+/-] (일반적)
#include<iostream> using namespace std; int main(void) { for(int line = 0; line < 5; line++) { for(int width = 0; width <= line; width++) { cout << "*"; } cout << endl; } return 0; }
[+/-] (템플릿 사용)
원래는 TMP(템플릿 메타 프로그래밍)을 하려 하였으나 실패했다.
#include <iostream> template<int x> struct Star : public Star<x-1> { Star() { std::cout << std::string(x, '*').c_str() << std::endl; } }; template<> struct Star<0> { // }; int main(int argc, char * argv[]) { Star<5> _Star; return 0; }
[+/-] C#
using System; class Star{ public static void Main(){ for (int a=1; a<6; a++){ for (int b=0; b<a; b++){ Console.Write("*"); } Console.WriteLine(""); } } }
[+/-] Common Lisp
(dotimes (j 5) (dotimes (i (1+ j)) (princ "*")) (fresh-line))
[+/-] Win32 API (C)
#include <windows.h> LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); HINSTANCE g_hInst; HWND hWndMain; LPCTSTR lpszClass=TEXT("Class"); int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance ,LPSTR lpszCmdParam,int nCmdShow) { HWND hWnd; MSG Message; WNDCLASS WndClass; g_hInst=hInstance; WndClass.cbClsExtra=0; WndClass.cbWndExtra=0; WndClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1); WndClass.hCursor=LoadCursor(NULL,IDC_ARROW); WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION); WndClass.hInstance=hInstance; WndClass.lpfnWndProc=WndProc; WndClass.lpszClassName=lpszClass; WndClass.lpszMenuName=NULL; WndClass.style=CS_HREDRAW | CS_VREDRAW; RegisterClass(&WndClass); hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT, NULL,(HMENU)NULL,hInstance,NULL); ShowWindow(hWnd,nCmdShow); while (GetMessage(&Message,NULL,0,0)) { TranslateMessage(&Message); DispatchMessage(&Message); } return (int)Message.wParam; } LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; switch (iMessage) { case WM_CREATE: hWndMain=hWnd; MessageBox(hWnd,TEXT("*\r\n**\r\n***\r\n****\r\n*****\r\n"),TEXT("별찍기"),MB_OK); return 0; case WM_PAINT: hdc=BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return(DefWindowProc(hWnd,iMessage,wParam,lParam)); }
[+/-] 프롤로그(Prolog)
star(0) :- nl. star(N) :- X is N-1, write(*), star(X). prymid(1) :- star(1). prymid(N) :- X is N-1, prymid(X), star(N).
[+/-] 개성있는 별 찍기
별 찍기의 범주 안에 들어가는 개성 있는 방법으로 별을 찍는다.
[+/-] C언어 별 찍기(1)
#include <stdio.h> int main() { printf("*"); return 0; }
[+/-] C언어 별 찍기(2)
#include <stdio.h> int main() { printf("☆★"); return 0; }
[+/-] C언어 별 찍기(3)
#include <stdio.h> int main(void) { int n, floor,cnt_star; n=floor=1; printf("Enter a Start"); scanf("%d",&cnt_star); while(n<=cnt_star){ floor=1; while(n>=floor){ if(n!=floor) printf("*"); else printf("*\n"); floor++; } n++; } return 0; }
[+/-] C언어 별 찍기(4)
루프 하나와 ASCII code를 이용하여 출력
#include <stdio.h> //ASCII code를 이용한 별 찍기. int main() { int star = 0x002A; int nline = 0x000A; char out; int width = 0; int line = 1; for (;width < 5; ((line == width)?(out = nline, line++, width = 0):(out = star, width++)), printf("%c", out)); return 0; }
[+/-] OpenGL(GLUT)
정12면체를 이루는 12개의 오각뿔을 역으로 한 별 모양의 폴리곤을 *로 찍음
#include <GL/glut.h> #include <stdlib.h> double vertex[][3] = { // first pentagon {-1.00000000, -1.00000000, 1.00000000}, { 0.00000000, -0.61803399, 1.61803399}, { 0.00000000, 0.61803399, 1.61803399}, {-1.00000000, 1.00000000, 1.00000000}, {-1.61803399, 0.00000000, 0.61803399}, // second pentagon { 0.00000000, -0.61803399, 1.61803399}, { 1.00000000, -1.00000000, 1.00000000}, { 1.61803399, 0.00000000, 0.61803399}, { 1.00000000, 1.00000000, 1.00000000}, { 0.00000000, 0.61803399, 1.61803399}, // third pentagon { 0.00000000, 0.61803399, 1.61803399}, { 1.00000000, 1.00000000, 1.00000000}, { 0.61803399, 1.61803399, 0.00000000}, {-0.61803399, 1.61803399, 0.00000000}, {-1.00000000, 1.00000000, 1.00000000}, // forth pentagon {-1.61803399, 0.00000000, 0.61803399}, {-1.00000000, 1.00000000, 1.00000000}, {-0.61803399, 1.61803399, 0.00000000}, {-1.00000000, 1.00000000, -1.00000000}, {-1.61803399, 0.00000000, -0.61803399}, // fifth pentagon { 1.00000000, 1.00000000, 1.00000000}, { 1.61803399, 0.00000000, 0.61803399}, { 1.61803399, 0.00000000, -0.61803399}, { 1.00000000, 1.00000000, -1.00000000}, { 0.61803399, 1.61803399, 0.00000000}, // sixth pentagon {-0.61803399, 1.61803399, 0.00000000}, { 0.61803399, 1.61803399, 0.00000000}, { 1.00000000, 1.00000000, -1.00000000}, { 0.00000000, 0.61803399, -1.61803399}, {-1.00000000, 1.00000000, -1.00000000}, // seventh pentagon {-1.61803399, 0.00000000, -0.61803399}, {-1.00000000, 1.00000000, -1.00000000}, { 0.00000000, 0.61803399, -1.61803399}, { 0.00000000, -0.61803399, -1.61803399}, {-1.00000000, -1.00000000, -1.00000000}, // eighth pentagon { 0.00000000, 0.61803399, -1.61803399}, { 1.00000000, 1.00000000, -1.00000000}, { 1.61803399, 0.00000000, -0.61803399}, { 1.00000000, -1.00000000, -1.00000000}, { 0.00000000, -0.61803399, -1.61803399}, // ninth pentagon {-1.00000000, -1.00000000, 1.00000000}, { 0.00000000, -0.61803399, 1.61803399}, { 1.00000000, -1.00000000, 1.00000000}, { 0.61803399, -1.61803399, 0.00000000}, {-0.61803399, -1.61803399, 0.00000000}, // tenth pentagon {-1.00000000, -1.00000000, 1.00000000}, {-0.61803399, -1.61803399, 0.00000000}, {-1.00000000, -1.00000000, -1.00000000}, {-1.61803399, 0.00000000, -0.61803399}, {-1.61803399, 0.00000000, 0.61803399}, // eleventh pentagon { 0.61803399, -1.61803399, 0.00000000}, { 1.00000000, -1.00000000, 1.00000000}, { 1.61803399, 0.00000000, 0.61803399}, { 1.61803399, 0.00000000, -0.61803399}, { 1.00000000, -1.00000000, -1.00000000}, // twelveth pentagon {-0.61803399, -1.61803399, 0.00000000}, { 0.61803399, -1.61803399, 0.00000000}, { 1.00000000, -1.00000000, -1.00000000}, { 0.00000000, -0.61803399, -1.61803399}, {-1.00000000, -1.00000000, -1.00000000}}; double r = 0; short cxWidth, nStarWidth; unsigned char cStar[64 * 64 * 3]; // star buffer bool bstop = false; void resize(int width, int height) { double rate = (double)nStarWidth; glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-1 * rate, rate, -1 * rate, rate, -1 * rate, rate); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glutPostRedisplay(); } void display(void) { short i, j, k; double dx = -7.9225, dy = 7.6775, dcw = 0.2475; // proper charactor location double center[3]; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(1, 1, 1, 1); glColor3d(0, 0, 0); glPushMatrix(); glRotated(r, 3, 2, 1); glScaled(1 / 2.75, 1 / 2.75, 1 / 2.75); // proper scaling for(i = 0; i < 12; i++) { center[0] = 0; center[1] = 0; center[2] = 0; for(j = 0; j < 5; j++) { center[0] += vertex[i * 5 + j][0]; center[1] += vertex[i * 5 + j][1]; center[2] += vertex[i * 5 + j][2]; } center[0] = center[0] / 5 * 2; center[1] = center[1] / 5 * 2; center[2] = center[2] / 5 * 2; for(j = 0; j < 5; j++) { glBegin(GL_TRIANGLES); glVertex3d(center[0], center[1], center[2]); glVertex3d(vertex[i * 5 + j][0], vertex[i * 5 + j][1], vertex[i * 5 + j][2]); glVertex3d(vertex[i * 5 + (j + 1) % 5][0], vertex[i * 5 + (j + 1) % 5][1], vertex[i * 5 + (j + 1) % 5][2]); glEnd(); } } glPopMatrix(); glReadPixels((cxWidth / 2) - 32, (cxWidth / 2) - 32, 64, 64, GL_RGB, GL_UNSIGNED_BYTE, cStar); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(1, 1, 1, 1); for(i = 0; i < 64; i++) { for(j = 0; j < 64; j++) { if(!cStar[(i * 64 + j) * 3]) { glRasterPos2d(dx + dcw * j, dy - dcw * i); glutBitmapCharacter(GLUT_BITMAP_8_BY_13, '*'); } } } glutSwapBuffers(); if(!bstop) r++; } void key(unsigned char key, int x, int y) { switch (key) { case 27 : case 'q': exit(0); break; case ' ': bstop = !bstop; break; } glutPostRedisplay(); } void idle(void) { glutPostRedisplay(); } int main(int argc, char *argv[]) { glutInit(&argc, argv); nStarWidth = glutBitmapWidth(GLUT_BITMAP_8_BY_13, '*'); cxWidth = 64 * nStarWidth; glutInitWindowSize(cxWidth, cxWidth); glutInitWindowPosition(10, 10); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutCreateWindow("active star printer"); glutReshapeFunc(resize); glutDisplayFunc(display); glutKeyboardFunc(key); glutIdleFunc(idle); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glutMainLoop(); return EXIT_SUCCESS; }
[+/-] Fractal 별찍기
java code라서 어떻게 올릴까 고민중임.
[+/-] Ruby언어 별 찍기 웹 서버
require 'socket' server = TCPServer.new 'localhost', 80 while(client = server.accept) client.print "HTTP/1.1 200/OK\r\nContent-type: text/html\r\n\r\n" client.print "<html><body><h1>*<br>**<br>***<br>****<br>*****</h1></body></html>" client.close end


