코딩문제 - 팰린드롬(palindrome) 확인

코딩문제 - 팰린드롬(palindrome) 확인

코딩문제 하나 만들어봐

문제: 주어진 문자열이 팰린드롬(palindrome)인지 확인하는 함수를 작성하라. 팰린드롬이란 앞으로 읽으나 뒤로 읽으나 같은 단어 또는 문장을 의미한다. 단, 입력된 문자열은 대소문자를 구분하지 않으며, 공백과 특수문자는 무시한다.

예시:

is_palindrome("A man, a plan, a canal: Panama") # True
is_palindrome("race a car") # False
is_palindrome("Was it a car or a cat I saw?") # True

힌트:

그걸 니가 풀어봐

코드 작성 연습이 필요하시다면, 다음과 같이 Python 함수를 작성하여 주어진 문자열이 팰린드롬인지 확인할 수 있습니다.

import re

def is_palindrome(s: str) -> bool:
    # 문자열을 소문자로 바꾸고, 정규식을 사용하여 공백과 특수문자를 제거한다.
    s = re.sub('[^a-z0-9]', '', s.lower())
    # 문자열을 뒤집어서 원래 문자열과 비교한다.
    return s == s[::-1]

위 함수는 입력으로 문자열 s를 받으며, True 또는 False를 반환합니다. 함수 내부에서는 문자열을 소문자로 바꾼 후, re 모듈을 사용하여 정규식 패턴 [^\w]를 이용하여 알파벳과 숫자를 제외한 모든 문자를 제거합니다. 그리고 문자열을 뒤집어서 원래 문자열과 비교하여 결과를 반환합니다.

예시:

print(is_palindrome("A man, a plan, a canal: Panama"))  # True
print(is_palindrome("race a car"))  # False
print(is_palindrome("Was it a car or a cat I saw?"))  # True

다른 프로그래밍 언어를 사용하는 경우에도, 비슷한 접근 방식으로 문제를 해결할 수 있습니다. 예를 들어, 다음은 JavaScript로 작성한 함수입니다.

function isPalindrome(s) {
  // 문자열을 소문자로 바꾸고, 정규식을 사용하여 공백과 특수문자를 제거한다.
  s = s.replace(/[^a-z0-9]/gi, '').toLowerCase();
  // 문자열을 뒤집어서 원래 문자열과 비교한다.
  return s === s.split('').reverse().join('');
}

위 함수는 입력으로 문자열 s를 받으며, true 또는 false를 반환합니다. 함수 내부에서는 문자열을 소문자로 바꾼 후, replace() 메서드와 정규식 /[^a-z0-9]/gi를 이용하여 알파벳과 숫자를 제외한 모든 문자를 제거합니다. 그리고 문자열을 뒤집어서 원래 문자열과 비교하여 결과를 반환합니다.

예시:

console.log(isPalindrome("A man, a plan, a canal: Panama"));  // true
console.log(isPalindrome("race a car"));  // false
console.log(isPalindrome("Was it a car or a cat I saw?"));  // true

다른 언어를 사용하는 경우에도, 비슷한 로직으로 구현하여 팰린드롬 여부를 확인할 수 있습니다.

다른 예로 C++로 작성한 함수를 살펴보겠습니다.

#include <string>
#include <algorithm>

bool is_palindrome(const std::string& s) {
  // 문자열을 소문자로 바꾸고, 정규식을 사용하여 공백과 특수문자를 제거한다.
  std::string cleaned_str(s);
  cleaned_str.erase(std::remove_if(cleaned_str.begin(), cleaned_str.end(), 
    [](char c) { return !std::isalnum(c); }), cleaned_str.end());
  std::transform(cleaned_str.begin(), cleaned_str.end(), cleaned_str.begin(), ::tolower);
  // 문자열을 뒤집어서 원래 문자열과 비교한다.
  return std::equal(cleaned_str.begin(), cleaned_str.end(), cleaned_str.rbegin());
}

위 함수는 입력으로 std::string 타입의 문자열 s를 받으며, true 또는 false를 반환합니다. 함수 내부에서는 문자열을 소문자로 바꾼 후, std::remove_if() 함수와 람다 함수를 이용하여 알파벳과 숫자를 제외한 모든 문자를 제거합니다. 그리고 std::transform() 함수를 이용하여 문자열을 소문자로 바꿉니다. 마지막으로 std::equal() 함수를 이용하여 문자열을 뒤집어서 원래 문자열과 비교하여 결과를 반환합니다.

예시:

#include <iostream>

int main() {
  std::cout << std::boolalpha << is_palindrome("A man, a plan, a canal: Panama") << std::endl;  // true
  std::cout << std::boolalpha << is_palindrome("race a car") << std::endl;  // false
  std::cout << std::boolalpha << is_palindrome("Was it a car or a cat I saw?") << std::endl;  // true
  return 0;
}

다른 언어를 사용하는 경우에도, 비슷한 로직으로 구현하여 팰린드롬 여부를 확인할 수 있습니다.

어셈블리어로 풀어봐

어셈블리어로 팰린드롬 문제를 푸는 것은 가능하지만, 상당히 복잡할 수 있습니다. 여기서는 x86 아키텍처와 NASM 어셈블리어를 사용하여 예시를 들어보겠습니다.

아래는 문자열을 입력으로 받아서 팰린드롬인지 여부를 판단하는 함수 is_palindrome의 어셈블리어 구현입니다. 이 예시에서는 대소문자를 구분하지 않고, 문자열 길이가 100 이하인 경우에 대해서만 동작합니다.

section .data

  msg db 'Enter a string: ', 0
  msglen equ $-msg

  prompt db 'The string is a palindrome.', 0
  promptlen equ $-prompt

  error db 'The string is not a palindrome.', 0
  errorlen equ $-error

section .bss

  buffer resb 100
  length resb 1

section .text

  global _start

is_palindrome:
  ; 함수 호출 시, 문자열 포인터는 eax 레지스터에 저장된다.
  push ebx
  push ecx
  push edx
  push esi
  push edi

  ; 문자열 길이를 계산한다.
  mov ecx, eax
  mov ebx, 0
  .loop1:
    cmp byte [ecx], 0
    je .endloop1
    inc ecx
    inc ebx
    cmp ebx, 100
    jg .toolong
    jmp .loop1
  .endloop1:
  mov [length], bl

  ; 문자열을 복사하면서 공백과 특수문자를 제거한다.
  mov esi, eax ; esi: 문자열 포인터
  mov edi, buffer ; edi: 복사 대상 버퍼 포인터
  .loop2:
    mov bl, [esi]
    cmp bl, 0
    je .endloop2
    cmp ebx, 32
    je .nextchar
    cmp ebx, 33
    je .nextchar
    cmp ebx, 34
    je .nextchar
    cmp ebx, 39
    je .nextchar
    cmp ebx, 44
    je .nextchar
    cmp ebx, 46
    je .nextchar
    cmp ebx, 58
    je .nextchar
    cmp ebx, 59
    je .nextchar
    cmp ebx, 63
    je .nextchar
    cmp ebx, 64
    je .nextchar
    cmp ebx, 95
    je .nextchar
    cmp ebx, 96
    je .nextchar
    cmp ebx, 123
    jge .endloop2
    cmp ebx, 97
    jl .endloop2
    mov [edi], bl
    inc edi
  .nextchar:
    inc esi
    cmp esi, eax
    jl .loop2
  .endloop2:

  ; 문자열의 반점에서 앞뒤로 비교해 나가며, 팰린드롬 여부를 판단한다.
  mov ecx, edi
  dec ecx ; ecx: 문자열 끝 위치

is_palindrome 함수의 어셈블리어 구현을 이어서 작성하겠습니다.

  mov esi, buffer ; esi: 문자열 시작 위치
  .loop3:
    cmp esi, ecx
    jge .palindrome ; esi >= ecx 이면 팰린드롬임
    mov al, [esi]
    mov bl, [ecx]
    cmp al, bl
    je .nextchar2
    cmp al, 'A'
    jl .nextchar2
    cmp al, 'Z'
    jle .uppercase
    cmp al, 'a'
    jl .nextchar2
    cmp al, 'z'
    jle .nextchar2
    jmp .nextchar2
  .uppercase:
    add al, 32
    cmp al, bl
    je .nextchar2
    jmp .nextchar2
  .nextchar2:
    inc esi
    dec ecx
    jmp .loop3
  .palindrome:
    ; 문자열이 팰린드롬인 경우
    mov eax, 4 ; write 시스템 콜
    mov ebx, 1 ; stdout 파일 디스크립터
    mov ecx, prompt ; 출력할 문자열
    mov edx, promptlen ; 출력할 문자열 길이
    int 0x80
    jmp .exit
  .toolong:
    ; 문자열이 100자 이상인 경우
    mov eax, 4 ; write 시스템 콜
    mov ebx, 1 ; stdout 파일 디스크립터
    mov ecx, error ; 출력할 문자열
    mov edx, errorlen ; 출력할 문자열 길이
    int 0x80
  .exit:
    ; 함수 호출 시, 문자열 포인터는 eax 레지스터에 저장된다.
    pop edi
    pop esi
    pop edx
    pop ecx
    pop ebx
    ret

_start:
  ; 사용자로부터 문자열을 입력받는다.
  mov eax, 4 ; write 시스템 콜
  mov ebx, 1 ; stdout 파일 디스크립터
  mov ecx, msg ; 출력할 문자열
  mov edx, msglen ; 출력할 문자열 길이
  int 0x80

  mov eax, 3 ; read 시스템 콜
  mov ebx, 0 ; stdin 파일 디스크립터
  mov ecx, buffer ; 읽어들일 버퍼 포인터
  mov edx, 100 ; 읽어들일 최대 길이
  int 0x80

  ; 문자열이 팰린드롬인지 여부를 판단한다.
  call is_palindrome

  ; 프로그램 종료
  mov eax, 1 ; exit 시스템 콜
  xor ebx, ebx ; 종료 코드 0
  int 0x80

위 코드에서 is_palindrome 함수는 문자열 포인터를 eax 레지스터에 저장한 후 호출됩니다. 함수 내부에서는 문자열 길이를 계산하고, 문자열을 복사하면서 공백과 특수문자를 제거합니다. 그리고 문자열의 반점

이어서 어셈블리어 구현을 설명하겠습니다.

위 코드에서 is_palindrome 함수는 문자열 포인터를 eax 레지스터에 저장한 후 호출됩니다. 함수 내부에서는 문자열 길이를 계산하고, 문자열을 복사하면서 공백과 특수문자를 제거합니다. 그리고 문자열의 반점에서 앞뒤로 비교해 나가며, 팰린드롬 여부를 판단합니다. 마지막으로, 팰린드롬인 경우 prompt 문자열을 출력하고, 100자 이상인 경우 error 문자열을 출력합니다.

위 코드는 예시를 위한 간단한 구현이므로, 실제 환경에서 사용하려면 추가적인 검증이 필요합니다. 또한, 다른 어셈블리어와 아키텍처에서는 다른 방식으로 구현해야 할 수 있습니다.

html로 이 문제를 풀어봐

HTML은 마크업 언어이므로, 자체적으로 문자열 처리와 비교 기능을 제공하지는 않습니다. 하지만 JavaScript를 이용하여 HTML 문서 안에서 팰린드롬 문제를 해결할 수 있습니다.

다음은 HTML에서 입력 폼과 결과를 출력하는 예시 코드입니다. 사용자가 문자열을 입력하고 "Check" 버튼을 클릭하면, JavaScript 함수 checkPalindrome가 실행되어 입력된 문자열이 팰린드롬인지 여부를 판단하고, 결과를 출력합니다.

<!DOCTYPE html>
<html>
  <head>
    <title>Palindrome Checker</title>
    <script>
      function checkPalindrome() {
        // 입력된 문자열을 가져온다.
        var str = document.getElementById("inputString").value;

        // 문자열을 소문자로 바꾸고, 정규식을 사용하여 공백과 특수문자를 제거한다.
        str = str.replace(/[^a-z0-9]/gi, '').toLowerCase();

        // 문자열을 뒤집어서 원래 문자열과 비교한다.
        if (str === str.split('').reverse().join('')) {
          document.getElementById("result").innerHTML = "The string is a palindrome.";
        } else {
          document.getElementById("result").innerHTML = "The string is not a palindrome.";
        }
      }
    </script>
  </head>
  <body>
    <h1>Palindrome Checker</h1>
    <form>
      <label for="inputString">Enter a string:</label>
      <input type="text" id="inputString" name="inputString">
      <input type="button" value="Check" onclick="checkPalindrome()">
    </form>
    <p id="result"></p>
  </body>
</html>

위 코드에서 checkPalindrome 함수는 입력 폼의 inputString 요소에서 문자열을 가져온 후, 문자열을 소문자로 바꾸고, replace() 메서드와 정규식 /[^a-z0-9]/gi를 이용하여 알파벳과 숫자를 제외한 모든 문자를 제거합니다. 그리고 문자열을 뒤집어서 원래 문자열과 비교하여 결과를 출력합니다. 출력 결과는 result 요소에 출력됩니다.

위 코드는 예시를 위한 간단한 구현이므로, 실제 환경에서 사용하려면 추가적인 검증이 필요합니다.

css로 이 문제를 풀어줘

CSS는 스타일 시트 언어이므로, 문자열 처리와 비교 기능을 직접적으로 제공하지는 않습니다. 하지만 HTML과 JavaScript와 함께 사용하여, HTML 요소의 디자인과 레이아웃을 제어할 수 있습니다. 따라서 이 문제를 CSS로만 풀어낼 수는 없습니다.

하지만, 예를 들어 HTML 폼 요소의 레이아웃과 디자인을 CSS로 변경하는 것은 가능합니다. 이 경우 CSS의 display, position, color, background-color, font-size 등의 속성을 사용하여 요소의 스타일을 변경할 수 있습니다. 예를 들어, 아래 코드는 입력 폼과 결과 출력 요소를 가로 방향으로 나란히 배치하고, 폰트 크기를 조정하고, 배경 색상과 테두리 색상을 변경하는 방법을 보여줍니다.

<!DOCTYPE html>
<html>
  <head>
    <title>Palindrome Checker</title>
    <style>
      body {
        background-color: #f7f7f7;
      }
      form {
        display: flex;
        flex-direction: row;
        align-items: center;
      }
      label {
        font-size: 18px;
      }
      input[type="text"] {
        font-size: 18px;
        padding: 10px;
        border: 2px solid #ccc;
        border-radius: 4px;
        margin-right: 10px;
        width: 100%;
        max-width: 300px;
        box-sizing: border-box;
      }
      input[type="button"] {
        font-size: 18px;
        background-color: #4CAF50;
        color: white;
        border: none;
        border-radius: 4px;
        padding: 10px 20px;
        cursor: pointer;
      }
      input[type="button"]:hover {
        background-color: #45a049;
      }
      #result {
        font-size: 18px;
        margin-top: 10px;
        padding: 10px;
        border: 2px solid #ccc;
        border-radius: 4px;
        background-color: #fff;
      }
    </style>
    <script>
      function checkPalindrome() {
        // 입력된 문자열을 가져온다.
        var str = document.getElementById("inputString").value;

        // 문자열을 소문자로 바꾸고, 정규식을 사용하여 공백과 특수문자를 제거한다.
        str = str.replace(/[^a-z0-9]/gi, '').toLowerCase();

        // 문자열을 뒤집어서 원래 문자열과 비교한다.
        if (str === str.split('').reverse().join('')) {
          document.getElementById("result").innerHTML = "The string is a palindrome.";
        } else {
          document.getElementById("result").innerHTML = "The string is not a palindrome.";
        }
      }
    </script>
  </head>
  <body>
    <h1>Palindrome Checker</h1>
    <form>
      <label for="inputString">Enter a string:</label>
      <input type="text" id="inputString" name="input

위 코드는 예시를 위한 간단한 구현이므로, 실제 환경에서 사용하려면 추가적인 검증이 필요합니다.

그리고 이번 경우와 같이 디자인과 레이아웃을 변경하는 경우, 반드시 웹 접근성과 사용자 경험을 고려해야 합니다. CSS 속성이나 HTML 요소를 이용하여 접근성을 저해하거나, 사용자가 입력을 할 수 없거나, 화면 해상도에 따라 레이아웃이 깨지는 등의 문제가 발생하지 않도록 신경 써야 합니다.