Machineboy空
Excercism - CryptoSquare : 문자열 ✅ 본문
문제요약
암호문을 출력하라. 과정은 아래와 같다.
input | If man was meant to stay on the ground, god would have given us roots. |
normalize | ifmanwasmeanttostayonthegroundgodwouldhavegivenusroots |
segment | "ifmanwas" "meanttos" "tayonthe" "groundgo" "dwouldha" "vegivenu" "sroots " |
encoded | imtgdvsfearwermayoogoanouuiontnnlvtwttddesaohghnsseoau |
2차 segment | "imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau " |
output |
"imtgdvs"
"fearwer" "mayoogo" "anouuio" "ntnnlvt" "wttddes" "aohghn " "sseoau " |
https://exercism.org/tracks/csharp/exercises/crypto-square/edit
난이도
Medium
풀이 포인트
풀이 포인트라기엔, 추후 공부해야 하는 몰랐던 문법 추려두겠다.
- Char.IsLetterOrDigit
- Math.Sqrt
- Math.Ceiling
- Math.Min
- string.Join()
REVIEW
아니 Excercism Medium 난이도 꽤 어렵다.
백준으로 silver 3 ~ 5는 될 것 같다...
워낙 암호화 단계가 길어서 찬찬히 살펴 보자.
1) normalize
- space and punctuation are removed : Char.IsLetterOrDigit
- down-cased : ToLower()
using System;
using System.Linq;
public static string NormalizedPlaintext(string plaintext)
{
// Char.IsLetterOrDigit : a letter or a decimal digit 인지 검사 하여 true/false
string normalized = new string(plaintext.Where(char.IsLetterOrDigit).ToArray());
// ToLower() : 소문자로 변경
normalized = normalized.ToLower();
}
2) 1차 segment
최대한 정사각형에 가깝게 정리한다.
- r * c >= length of message
- c >= r
- c - r <= 1
using System;
using System.Collections.Generic;
using System.Linq;
public static class CryptoSquare
{
private static int c = 0;
private static List<string> seg = new List<string>();
public static IEnumerable<string> PlaintextSegments(string plaintext)
{
int length = plaintext.Length;
double squareRoot = Math.Sqrt(length); // Math.Sqrt : 제곱근 구하기
c = (int)Math.Ceiling(squareRoot); // Math.Ceiling: 크거나 같은 최소 정수값 반환
for(int i = 0; i < length; i += c)
{
// Substring(시작 인덱스, 길이)
string segment = plaintext.Substring(i, Math.Min(c, length - i));
seg.Add(segment);
}
return seg;
}
}

3) encoded
segment 결과를 세로로 읽는다.
// 내가 시도한 코드.. 몇개의 에러 케이스가 뜬다..
using System;
using System.Collections.Generic;
using System.Linq;
public static class CryptoSquare
{
// Normalize the plaintext by removing non-alphanumeric characters and converting to lowercase
public static string NormalizedPlaintext(string plaintext)
{
return new string(plaintext.Where(char.IsLetterOrDigit).ToArray()).ToLower();
}
// Break plaintext into segments of size c
public static IEnumerable<string> PlaintextSegments(string plaintext)
{
int length = plaintext.Length;
double squareRoot = Math.Sqrt(length);
int c = (int)Math.Ceiling(squareRoot);
var segments = new List<string>();
for (int i = 0; i < length; i += c)
{
string segment = plaintext.Substring(i, Math.Min(c, length - i));
segments.Add(segment);
}
return segments;
}
// Encode the plaintext by reading columns of the plaintext segments
public static string Encoded(string plaintext)
{
var segments = PlaintextSegments(plaintext).ToList();
if (!segments.Any()) return string.Empty;
int c = segments.First().Length;
var encodedSegments = new List<string>();
for (int i = 0; i < c; i++)
{
string encoded = "";
foreach (string segment in segments)
{
if (i < segment.Length)
{
encoded += segment[i];
}
}
encodedSegments.Add(encoded);
}
// Join with a trailing space included
return string.Join(" ", encodedSegments) + " ";
}
// Return the final ciphertext
public static string Ciphertext(string plaintext)
{
if (string.IsNullOrWhiteSpace(plaintext)) return string.Empty;
string normalized = NormalizedPlaintext(plaintext);
return Encoded(normalized);
}
}
CODE
// 모범 풀이
using System;
using System.Collections.Generic;
using System.Linq;
public static class CryptoSquare
{
public static string Ciphertext(string plaintext) =>
plaintext.Length == 0 ? string.Empty : string.Join(" ", plaintext.Normalized().Rows().Cols());
private static string Normalized(this string str) =>
new(str.ToLowerInvariant().Where(char.IsLetterOrDigit).ToArray());
private static int Size(this string str) => (int)Math.Ceiling(Math.Sqrt(str.Length));
private static string[] Rows(this string str)
{
var size = str.Size();
return str.Chunks(size).Select(row => row.PadRight(size)).ToArray();
}
private static IEnumerable<string> Cols(this string[] rows) =>
Enumerable.Range(0, rows[0].Length)
.Select(i => new string(rows.Select(row => row[i]).ToArray()));
private static IEnumerable<string> Chunks(this string str, int size)
{
for (var i = 0; i < str.Length; i += size)
yield return str.Substring(i, Math.Min(str.Length - i, size));
}
}
using System;
using System.Collections.Generic;
public static class CryptoSquare
{
public static string NormalizedPlaintext(string plaintext)
{
string normalized="";
foreach (char c in plaintext)
{
char lc = Char.ToLower(c);
if ((lc>='a' && lc <='z') || (lc<='9' && lc>='0')) {
normalized += lc;
}
}
return normalized;
}
public static IEnumerable<string> PlaintextSegments(string plaintext)
{
List<string> seg = new List<string>();
string input = NormalizedPlaintext(plaintext);
Console.WriteLine("normalized_plain_text="+ input);
int nlength= input.Length;
if (nlength==0) return seg;
int ncol = (int) Math.Ceiling(Math.Sqrt((double) nlength));
int nrow = (int) Math.Ceiling((double) nlength/ (double) ncol);
for (int ifrom = 0; ifrom< nlength; ifrom += ncol) {
int ilen = (ifrom + ncol >= nlength) ? (nlength-ifrom) : ncol;
seg.Add(input.Substring(ifrom, ilen));
}
return seg;
}
public static string Encoded(string plaintext)
{
return Ciphertext(plaintext);
}
public static string Ciphertext(string plaintext)
{
string cipher="";
if (plaintext.Length ==0) return cipher;
List<string> segments = (List<string>) PlaintextSegments(plaintext);
List<string> cipheredsegments = new List<string>();
for (int jj=0; jj<segments[0].Length; jj++) {
string colstring="";
for (int ii=0; ii<segments.Count; ii++) {
if (jj< segments[ii].Length) {
cipher += segments[ii][jj];
colstring += segments[ii][jj];
} else colstring += ' ';
}
cipheredsegments.Add(colstring);
}
string nct = "";
for (int ii=0; ii< cipheredsegments.Count; ii++) {
if (ii != 0) nct += " ";
nct += cipheredsegments[ii];
}
return nct;
}
}
아직 자꾸 내 코드는 테스트 케이스 2개 정도를 통과하지 못한다...
'Computer > Coding Test' 카테고리의 다른 글
Excercism - Beer Song : 문자열 개행 (0) | 2025.01.24 |
---|---|
Excercism - Rail Fence Cipher : 지그재그, 1,-1 방향 조절 (0) | 2025.01.23 |
Excercism - Binary Search : 이진탐색, 이진탐색 트리 (0) | 2025.01.22 |
Excercism - Resister Color : Dictionary, Array (0) | 2025.01.22 |
Excercism - Conway's Game of Life : DFS (0) | 2025.01.17 |