숫자를 입력 받아서 '#'으로 출력하기

Rust 공부하기 위해 Rust에서 짤 문제를 먼저 C#으로 짜봤습니다.

문제

숫자를 입력받아 '#'으로 이루어진 숫자로 출력하시오

결과

image

소스코드

using static System.Console;

// 문제) 숫자를 입력받아서 '#'으로 이루어진 숫자로 출력하시오.
// 예시) ? 312
// ###  #  ###
//   #  #    #
// ###  #  ###    
//   #  #  # 
// ###  #  ###
//
// 풀이 전략:
// - 숫자는 너비 3, 높이 5로 한다.
// - 배열로 숫자를 표현한다. 숫자 값이 배열 인덱스가 되도록 한다.

var nums = new[,]
{
    // 0
    { 0b111, 0b101, 0b101, 0b101, 0b111 },
    // 1
    { 0b010, 0b010, 0b010, 0b010, 0b010 },
    // 2
    { 0b111, 0b001, 0b111, 0b100, 0b111 },
    // 3
    { 0b111, 0b001, 0b111, 0b001, 0b111 },
    // 4
    { 0b101, 0b101, 0b111, 0b001, 0b001 },
    // 5
    { 0b111, 0b100, 0b111, 0b001, 0b111 },
    // 6
    { 0b100, 0b100, 0b111, 0b101, 0b111 },
    // 7
    { 0b111, 0b001, 0b001, 0b001, 0b001 },
    // 8
    { 0b111, 0b101, 0b111, 0b101, 0b111 },
    // 9
    { 0b111, 0b101, 0b111, 0b001, 0b001 }
};

var lines = nums.GetUpperBound(1) + 1;

while (true)
{
    Write("? ");
    var strNum = ReadLine().Trim();
    var result = int.TryParse(strNum, out var _);
    if (result == false)
        continue;

    for (var y = 0; y < lines; y++)
    {
        foreach (var c in strNum)
        {
            var num = c - '0';

            Write(GetLine(nums[num, y]));
            Write(GetMargin());
        }
        WriteLine();
    }
}

string GetLine(int v) => v switch
{
    0b000 => "   ",
    0b001 => "  #",
    0b010 => " # ",
    0b011 => " ##",
    0b100 => "#  ",
    0b101 => "# #",
    0b110 => "## ",
    0b111 => "###",
    _ => "   ",
};

string GetMargin() => "  ";

좀 더 효율적인 코드 댓글로 달아주세요!

좋아요 4

혹시 가능하다면 프로파일러를 돌린 결과를 더 붙여주시면 이후에 올라오는 코드와 비교했을 때 더 평가가 쉽지 않을까 싶어요!

좋아요 2

digital display를 표현하는 문제와 비슷한 것 같아서, 일단 bit operator로 어떤 부분만 '#'으로 치환할지 결정하도록 고치면 좀 더 효율적이지 않을까 생각해봤습니다.

using static System.Console;

// 문제) 숫자를 입력받아서 '#'으로 이루어진 숫자로 출력하시오.
// 예시) ? 312
// ###  #  ###
//   #  #    #
// ###  #  ###    
//   #  #  # 
// ###  #  ###
//
// 풀이 전략:
// - 숫자는 너비 3, 높이 5로 한다.
// - 배열로 숫자를 표현한다. 숫자 값이 배열 인덱스가 되도록 한다.

var nums = new[,]
{
    // 0
    { 0b111, 0b101, 0b101, 0b101, 0b111 },
    // 1
    { 0b010, 0b010, 0b010, 0b010, 0b010 },
    // 2
    { 0b111, 0b001, 0b111, 0b100, 0b111 },
    // 3
    { 0b111, 0b001, 0b111, 0b001, 0b111 },
    // 4
    { 0b101, 0b101, 0b111, 0b001, 0b001 },
    // 5
    { 0b111, 0b100, 0b111, 0b001, 0b111 },
    // 6
    { 0b100, 0b100, 0b111, 0b101, 0b111 },
    // 7
    { 0b111, 0b001, 0b001, 0b001, 0b001 },
    // 8
    { 0b111, 0b101, 0b111, 0b101, 0b111 },
    // 9
    { 0b111, 0b101, 0b111, 0b001, 0b001 }
};

var buffer = new char[6];
buffer[4] = buffer[5] = '\u0020';

while (true)
{
	Write("? ");
	var strNum = ReadLine();

	for (var y = 0; y <= nums.GetUpperBound(1); y++)
	{
		for (var z = 0; z < strNum.Length; z++)
		{
			var num = strNum[z] - '\u0030';
			if (num < 0 || num > 9)
				continue;

			var v = nums[num, y];
			buffer[0] = ((v & (1 << 3)) == 0 ? '\u0020' : '\u0023');
			buffer[1] = ((v & (1 << 2)) == 0 ? '\u0020' : '\u0023');
			buffer[2] = ((v & (1 << 1)) == 0 ? '\u0020' : '\u0023');
			buffer[3] = ((v & (1 << 0)) == 0 ? '\u0020' : '\u0023');
			Write(buffer, 0, 6);
		}
		WriteLine();
	}
}

좀 더 아이디어가 떠올랐는데, 배열을 매번 새로 만들 필요가 없군요. ㅎㅎ

좋아요 3

문제와 관련 없는데, 옛날에 써 둔 글이 생각나는군요. ^^

.NET Framework: 498. C#으로 간단하게 만들어 본 ASCII Art 프로그램 (sysnet.pe.kr)

좋아요 5

yield를 쓰면 코드를 좀 더 깔끔하게 만들 수 있을 것 같은데요, 버퍼를 둬서 한글자씩 찍는게 아니라 라인별로 각 글자의 가로 줄을 출력해야하기 때문입니다.

좋아요 1

장준영 님의 Haskell 코드 입니다. 코드가 깔끔하고 아름답습니다. ( 정확한 의미는 잘 모르겠지만요; ) 코드 작성해주셔서 감사 드립니다.

좋아요 1

Rust로 짠 코드를 공유 합니다. Rust의 고급 기능을 이용하면 코드가 좀 더 심플해지겠지만 아직 지금 제 수준의 전개는 이정도 인것 같습니다. 코딩하면서 흥미로운 점은 Rust 언어는 컴파일 오류를 곧잘 뿜어내는 언어라는게 신박헸고, 그럼에도 불구하고 어떻게 수정하면 된다고 친절하게 가이드 주는것도 신박했습니다.

use std::io::{self, Write};

fn main() {
    // 숫자를 비트로 표현하여 할당
    let nums = [
        /* 0 */ [0b111, 0b101, 0b101, 0b101, 0b111],
        /* 1 */ [0b010, 0b010, 0b010, 0b010, 0b010],
        /* 2 */ [0b111, 0b001, 0b111, 0b100, 0b111],
        /* 3 */ [0b111, 0b001, 0b111, 0b001, 0b111],
        /* 4 */ [0b101, 0b101, 0b111, 0b001, 0b001],
        /* 5 */ [0b111, 0b100, 0b111, 0b001, 0b111],
        /* 6 */ [0b100, 0b100, 0b111, 0b101, 0b111],
        /* 7 */ [0b111, 0b001, 0b001, 0b001, 0b001],
        /* 8 */ [0b111, 0b101, 0b111, 0b101, 0b111],
        /* 9 */ [0b111, 0b101, 0b111, 0b001, 0b001],
    ];

    loop {
        // 숫자 입력
        let mut input = String::new();
        print!("? ");
        io::stdout().flush().unwrap();
        io::stdin().read_line(&mut input).expect("Invalid input.");

        // 공백 제거 후 더이상 입력 값을 수정하지 않으므로 다시 input에 할당
        let input = input.trim();
        // match input.parse::<u64>() {
        //     Err(_) => continue,
        //     _ => (),
        // }
        // 입력 값이 숫자가 아닌경우 처리하지 않음
        if let Err(_) = input.parse::<u64>() {
            continue;
        }

        for y in 0..nums[0].len() {
            for c in input.chars() {
                let v = c as i32 - '0' as i32;

                print!("{}", get_line(nums[v as usize][y]));
                print!("{}", get_margin());
            }
            println!();
        }
    }
}

fn get_line(v: i32) -> &'static str {
    match v {
        0b001 => "  #",
        0b010 => " # ",
        0b011 => " ##",
        0b100 => "#  ",
        0b101 => "# #",
        0b110 => "## ",
        0b111 => "###",
        _ => "   ",
    }
}

fn get_margin() -> &'static str {
    "  "
}
좋아요 1

무식하게(?) 풀어보았습니다.

using System;
using System.Text;

var digits = new[,]
{
    {"  #####   ", " ##   ##  ", "##     ## ", "##     ## ", "##     ## ", " ##   ##  ", "  #####   "},
    {"   ##   ", " ####   ", "   ##   ", "   ##   ", "   ##   ", "   ##   ", " ###### "},
    {" #######  ", "##     ## ", "       ## ", " #######  ", "##        ", "##        ", "######### "},
    {" #######  ", "##     ## ", "       ## ", " #######  ", "       ## ", "##     ## ", " #######  "},
    {"##        ", "##    ##  ", "##    ##  ", "##    ##  ", "######### ", "      ##  ", "      ##  "},
    {"######## ", "##       ", "##       ", " ####### ", "      ## ", "##    ## ", " ####### "},
    {" #######  ", "##     ## ", "##        ", "########  ", "##     ## ", "##     ## ", " #######  "},
    {"######### ", "##     ## ", "##     ## ", "     ##   ", "   ##     ", "   ##     ", "   ##     "},
    {" #######  ", "##     ## ", "##     ## ", " #######  ", "##     ## ", "##     ## ", " #######  "},
    {" #######  ", "##     ## ", "##     ## ", " ######## ", "       ## ", "       ## ", " #######  "}
};
var input = Array.ConvertAll(Console.ReadLine()?.ToCharArray()!, c => (int) char.GetNumericValue(c));
var len = input.Length;
var sb = new StringBuilder();

for (var i = 0; i < 7; i++)
{
    for (var j = 0; j < len; j++)
    {
        sb.Append($"{digits[input[j], i]}   ");
    }

    sb.AppendLine();
}

Console.WriteLine(sb);


실행 결과:

02

03

좋아요 2

우와 안무식합니다. 코드 공유 고마워요!

좋아요 2

우와. 깅강민 님이 파이썬 코드로 작성하신 코드 입니다. 감사합니다.

inputNumberList = list(map(int, input()))
inputNumberListLength = len(inputNumberList)
numberList = [31599, 9362, 29671, 29647, 23497, 31183, 31215, 29257, 31727, 31695]
stringList = ['', '', '', '', '']
for i in range(inputNumberListLength):
bitList = list(map(lambda string : '#' if string == '1' else ' ', '0' + bin(numberList[inputNumberList[i]])[2:]))
bitListLength = len(bitList)
seperatingString = ' ' if i != inputNumberListLength - 1 else ''
for j in range(1, 6):
stringList[5-j] += bitList[bitListLength-3*j] + bitList[bitListLength-3*j+1] + bitList[bitListLength-3*j+2] + seperatingString
print(stringList[0], stringList[1], stringList[2], stringList[3], stringList[4], sep='\n')