{ }codelper
포함 검사그리고·또는P0098

비밀번호 규칙 검사

첫 줄에 비밀번호 수 n이 주어지고, 다음 n줄에 비밀번호가 하나씩 주어진다.
특수 글자는 !@#$%^&* 여덟 개다.
비밀번호마다 다음 여섯 규칙을 검사하라. 1.
길이가 8 이상 16 이하다. 2.
영어 대문자(A~Z)가 하나 이상 있다. 3.
영어 소문자(a~z)가 하나 이상 있다. 4.
숫자(0~9)가 하나 이상 있다. 5.
특수 글자가 하나 이상 있다. 6.
모든 글자가 영어 글자, 숫자, 특수 글자 가운데 하나다. 모든 규칙을 지키면 "통과"를, 아니면 어긴 규칙 번호를 모두 작은 것부터 빈칸 하나로 띄워 한 줄에 출력하라.

입력
1 ≤ n ≤ 100, 비밀번호는 빈칸 없는 글자(아스키 코드 33~126) 1~30개
출력
비밀번호마다 한 줄: "통과" 또는 어긴 규칙 번호들
예시 1 · stdin
4
Abcdef1!
abc
Pass_word1
Hello12345World!!
stdout
통과
1 2 4 5
5 6
1
main.py
입력(stdin)

실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).

$ 준비됐어요

코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.

다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이

규칙 2~5는 "하나라도 있나"(any), 규칙 6은 "모두 그런가"(all)예요.
6을 any로 쓰면 허용 글자가 하나만 있어도 통과해요.
어긴 규칙을 모두 내야 하니 else if 사슬이 아니라 if를 여섯 번 따로 써요.
사슬로 쓰면 처음 어긴 규칙 하나만 나와요.
길이는 8 <= len <= 16처럼 양 끝을 넣어요.
범위를 묻는 방법이 언어마다 달라요.
Python만 "A" <= c <= "Z"를 이어 쓸 수 있어요.
C·C++·JS에서 'A' <= c <= 'Z'는 ('A' <= c) <= 'Z'로 읽혀요.
C·C++에서는 늘 참이고(요즘 clang은 아예 오류로 막아요), JS에서는 참거짓과 'Z'를 수로 비교해서 늘 거짓이에요.
TS·Java·C#은 컴파일 오류예요.
그래서 c >= 'A' && c <= 'Z'로 써요.
그리고(and)·또는(or)·아니다(not)는 Python and·or·not, 나머지 언어 &&·||·!이고, 어디서나 and가 or보다 먼저 묶여요(a and b or c는 (a and b) or c).
"이 글자가 특수 글자 목록에 있나"는 Python c in s, JS·TS s.includes(c), Java s.indexOf(c) >= 0, C# s.Contains(c), C++ s.find(c) != npos, C strchr(s, c)로 물어요.
크레이콘은 SPECIAL.있나(c)이고 그리고·또는·아니다는 &&·||·!예요.

Pythonmain.py · 25 줄
SPECIAL = "!@#$%^&*"  def broken_rules(pw):    broken = []    if not 8 <= len(pw) <= 16:        broken.append(1)    if not any("A" <= c <= "Z" for c in pw):        broken.append(2)    if not any("a" <= c <= "z" for c in pw):        broken.append(3)    if not any("0" <= c <= "9" for c in pw):        broken.append(4)    if not any(c in SPECIAL for c in pw):        broken.append(5)    # 6: 모든 글자가 영어 글자·숫자·특수 글자 가운데 하나    if not all(c.isascii() and c.isalnum() or c in SPECIAL for c in pw):        broken.append(6)    return broken  n = int(input())for _ in range(n):    broken = broken_rules(input().strip())    print(" ".join(map(str, broken)) if broken else "통과")
JavaScriptmain.js · 27 줄
const lines = require("fs").readFileSync(0, "utf8").split("\n");const n = Number(lines[0]);const SPECIAL = "!@#$%^&*";const isUpper = (c) => c >= "A" && c <= "Z";const isLower = (c) => c >= "a" && c <= "z";const isDigit = (c) => c >= "0" && c <= "9";const isSpecial = (c) => SPECIAL.includes(c); function brokenRules(pw) {  const chars = [...pw];  const broken = [];  if (!(pw.length >= 8 && pw.length <= 16)) broken.push(1);  if (!chars.some(isUpper)) broken.push(2);  if (!chars.some(isLower)) broken.push(3);  if (!chars.some(isDigit)) broken.push(4);  if (!chars.some(isSpecial)) broken.push(5);  // 6: 모든 글자가 영어 글자·숫자·특수 글자 가운데 하나  if (!chars.every((c) => isUpper(c) || isLower(c) || isDigit(c) || isSpecial(c))) broken.push(6);  return broken;} const out = [];for (let i = 1; i <= n; i++) {  const broken = brokenRules(lines[i].trim());  out.push(broken.length ? broken.join(" ") : "통과");}console.log(out.join("\n"));
TypeScriptmain.ts · 28 줄
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const n: number = Number(lines[0]);const SPECIAL = "!@#$%^&*";const isUpper = (c: string): boolean => c >= "A" && c <= "Z";const isLower = (c: string): boolean => c >= "a" && c <= "z";const isDigit = (c: string): boolean => c >= "0" && c <= "9";const isSpecial = (c: string): boolean => SPECIAL.includes(c); function brokenRules(pw: string): number[] {  const chars: string[] = [...pw];  const broken: number[] = [];  if (!(pw.length >= 8 && pw.length <= 16)) broken.push(1);  if (!chars.some(isUpper)) broken.push(2);  if (!chars.some(isLower)) broken.push(3);  if (!chars.some(isDigit)) broken.push(4);  if (!chars.some(isSpecial)) broken.push(5);  // 6: 모든 글자가 영어 글자·숫자·특수 글자 가운데 하나  if (!chars.every((c) => isUpper(c) || isLower(c) || isDigit(c) || isSpecial(c))) broken.push(6);  return broken;} const out: string[] = [];for (let i = 1; i <= n; i++) {  const broken: number[] = brokenRules(lines[i].trim());  out.push(broken.length ? broken.join(" ") : "통과");}console.log(out.join("\n"));
JavaMain.java · 44 줄
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.List; public class Main {    static final String SPECIAL = "!@#$%^&*";     static List<Integer> brokenRules(String pw) {        boolean upper = false, lower = false, digit = false, special = false, allAllowed = true;        for (char c : pw.toCharArray()) {            boolean u = c >= 'A' && c <= 'Z', l = c >= 'a' && c <= 'z', d = c >= '0' && c <= '9';            boolean s = SPECIAL.indexOf(c) >= 0;            upper |= u;            lower |= l;            digit |= d;            special |= s;            // 6: 모든 글자가 넷 중 하나 — 하나라도 아니면 거짓            if (!(u || l || d || s)) allAllowed = false;        }        List<Integer> broken = new ArrayList<>();        if (!(pw.length() >= 8 && pw.length() <= 16)) broken.add(1);        if (!upper) broken.add(2);        if (!lower) broken.add(3);        if (!digit) broken.add(4);        if (!special) broken.add(5);        if (!allAllowed) broken.add(6);        return broken;    }     public static void main(String[] args) throws IOException {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        int n = Integer.parseInt(in.readLine().trim());        StringBuilder out = new StringBuilder();        for (int i = 0; i < n; i++) {            List<Integer> broken = brokenRules(in.readLine().trim());            if (broken.isEmpty()) out.append("통과");            else for (int j = 0; j < broken.size(); j++) out.append(j > 0 ? " " : "").append(broken.get(j));            out.append('\n');        }        System.out.print(out);    }}
C#Main.cs · 36 줄
using System;using System.Collections.Generic;using System.Linq; class Program{    const string Special = "!@#$%^&*";     static bool IsUpper(char c) => c >= 'A' && c <= 'Z';    static bool IsLower(char c) => c >= 'a' && c <= 'z';    static bool IsDigit(char c) => c >= '0' && c <= '9';    static bool IsSpecial(char c) => Special.Contains(c);     static List<int> BrokenRules(string pw)    {        var broken = new List<int>();        if (!(pw.Length >= 8 && pw.Length <= 16)) broken.Add(1);        if (!pw.Any(IsUpper)) broken.Add(2);        if (!pw.Any(IsLower)) broken.Add(3);        if (!pw.Any(IsDigit)) broken.Add(4);        if (!pw.Any(IsSpecial)) broken.Add(5);        // 6: 모든 글자가 영어 글자·숫자·특수 글자 가운데 하나        if (!pw.All(c => IsUpper(c) || IsLower(c) || IsDigit(c) || IsSpecial(c))) broken.Add(6);        return broken;    }     static void Main()    {        int n = int.Parse(Console.ReadLine());        for (int i = 0; i < n; i++)        {            var broken = BrokenRules(Console.ReadLine().Trim());            Console.WriteLine(broken.Count == 0 ? "통과" : string.Join(" ", broken));        }    }}
C++main.cpp · 37 줄
#include <algorithm>#include <iostream>#include <string>#include <vector> const std::string SPECIAL = "!@#$%^&*"; bool is_upper(char c) { return c >= 'A' && c <= 'Z'; }bool is_lower(char c) { return c >= 'a' && c <= 'z'; }bool is_digit(char c) { return c >= '0' && c <= '9'; }bool is_special(char c) { return SPECIAL.find(c) != std::string::npos; } std::vector<int> broken_rules(const std::string& pw) {    std::vector<int> broken;    if (!(pw.size() >= 8 && pw.size() <= 16)) broken.push_back(1);    if (std::none_of(pw.begin(), pw.end(), is_upper)) broken.push_back(2);    if (std::none_of(pw.begin(), pw.end(), is_lower)) broken.push_back(3);    if (std::none_of(pw.begin(), pw.end(), is_digit)) broken.push_back(4);    if (std::none_of(pw.begin(), pw.end(), is_special)) broken.push_back(5);    // 6: 모든 글자가 영어 글자·숫자·특수 글자 가운데 하나    if (!std::all_of(pw.begin(), pw.end(), [](char c) { return is_upper(c) || is_lower(c) || is_digit(c) || is_special(c); }))        broken.push_back(6);    return broken;} int main() {    int n;    std::cin >> n;    for (int i = 0; i < n; i++) {        std::string pw;        std::cin >> pw;        std::vector<int> broken = broken_rules(pw);        if (broken.empty()) std::cout << "통과";        for (std::size_t j = 0; j < broken.size(); j++) std::cout << (j ? " " : "") << broken[j];        std::cout << '\n';    }}
Cmain.c · 40 줄
#include <stdio.h>#include <string.h> static const char *SPECIAL = "!@#$%^&*"; // c가 SPECIAL에 있나. strchr는 c == '\0'일 때도 끝의 '\0'을 찾아 주므로 c를 먼저 본다static int is_special(char c) { return c != '\0' && strchr(SPECIAL, c) != NULL; } int main(void) {    int n;    char pw[32];    scanf("%d", &n);    for (int i = 0; i < n; i++) {        scanf("%31s", pw);        int len = strlen(pw);        int upper = 0, lower = 0, digit = 0, special = 0, all_allowed = 1;        for (int j = 0; j < len; j++) {            char c = pw[j];            int u = c >= 'A' && c <= 'Z', l = c >= 'a' && c <= 'z', d = c >= '0' && c <= '9', s = is_special(c);            upper |= u;            lower |= l;            digit |= d;            special |= s;            if (!(u || l || d || s)) all_allowed = 0;        }        int broken[6], k = 0;        if (!(len >= 8 && len <= 16)) broken[k++] = 1;        if (!upper) broken[k++] = 2;        if (!lower) broken[k++] = 3;        if (!digit) broken[k++] = 4;        if (!special) broken[k++] = 5;        if (!all_allowed) broken[k++] = 6;        if (k == 0) puts("통과");        else {            for (int j = 0; j < k; j++) printf(j ? " %d" : "%d", broken[j]);            putchar('\n');        }    }    return 0;}
Craykonmain.cray · 66 줄
SPECIAL = "!@#$%^&*"; 어긴규칙(pw){    upper = 거짓;    lower = 거짓;    digit = 거짓;    special = 거짓;    allAllowed = 참;    각각 (c 에서 pw)    {        u = c >= "A" && c <= "Z";        l = c >= "a" && c <= "z";        d = c >= "0" && c <= "9";        s = SPECIAL.있나(c);        upper = upper || u;        lower = lower || l;        digit = digit || d;        special = special || s;        // 6: 모든 글자가 넷 중 하나 — 하나라도 아니면 거짓        만약 (!(u || l || d || s))        {            allAllowed = 거짓;        }    }    broken = [];    만약 (!(pw.길이 >= 8 && pw.길이 <= 16))    {        broken.넣기(1);    }    만약 (!upper)    {        broken.넣기(2);    }    만약 (!lower)    {        broken.넣기(3);    }    만약 (!digit)    {        broken.넣기(4);    }    만약 (!special)    {        broken.넣기(5);    }    만약 (!allAllowed)    {        broken.넣기(6);    }    돌려주기 broken;} n = 콘솔.줄읽기().수로변환();반복 (i = 0; i < n; i++){    broken = 어긴규칙(콘솔.줄읽기().공백제거());    만약 (broken.개수 == 0)    {        콘솔.쓰기("통과");    }    아니면    {        콘솔.쓰기(broken.잇기(" "));    }}