LoginSignup
2
0

More than 5 years have passed since last update.

ずんだの菱形アルファベット問題 Python3 & SQL編

Posted at

もとねた: ずんだの菱形アルファベット問題 Ruby編

Python3で、まずは「ふつう」に回答してみました。もとねたでは実行時引数を読み込んでいましたが、以下の解答では標準入力の1行目をnとしています。

def draw(n):
    if n % 2 == 0:
        return 'invalid'

    mid = n // 2
    matrix = [['_'] * n for _ in range(n)]
    for x, alphabet in zip(range(n), 'abcdefghijklmnopqrstuvwxyz'):
        y = abs(mid - x) - mid
        matrix[x][mid + y] = matrix[x][mid - y] = alphabet

    return '\n'.join(''.join(row) for row in matrix)

if __name__ == '__main__':
    n = int(input())
    print(draw(n))

次はPython3の「ふつう」ではない解答、つまり1行野郎で解いたものが以下になります。これも「ふつう」の解答と同様に標準入力の1行目をnとします。

print((lambda n : 'invalid' if n % 2 == 0 else '\n'.join(''.join(ch if y in (abs(n // 2 - x), (n - 1) - abs(n // 2 - x)) else '_' for y in range(n)) for x, ch in zip(range(n), 'abcdefghijklmnopqrstuvwxyz')))(int(input())))

たとえばPython3のREPLなどをつかって、上記の1行野郎を実行してみると、想定通りの結果が得られることがわかります。

$ python3
Python 3.6.5 (default, Apr  1 2018, 05:46:30)
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print((lambda n : 'invalid' if n % 2 == 0 else '\n'.join(''.join(ch if y in (abs(n // 2 - x), (n - 1) - abs(n // 2 - x)) else '_' for y in range(n)) for x, ch in zip(range(n), 'abcdefghijklmnopqrstuvwxyz')))(int(input())))
5
__a__
_b_b_
c___c
_d_d_
__e__
>>> print((lambda n : 'invalid' if n % 2 == 0 else '\n'.join(''.join(ch if y in (abs(n // 2 - x), (n - 1) - abs(n // 2 - x)) else '_' for y in range(n)) for x, ch in zip(range(n), 'abcdefghijklmnopqrstuvwxyz')))(int(input())))
2
invalid

Python3だけではさみしいのでSQLでも解答してみました。以下がその解答になります。
入力はバインド変数:Nとして1から25までの整数を与えます。動作確認にはPostgreSQL 10.5を利用していますが、言語依存の機能はさほど利用していないので、多少の読み替えなどはあったとしても、基本的にはほかのDBMSでも動く--はず(´・ω・`)

WITH 
RECURSIVE alphabets(x, alphabet, list) AS (
    SELECT -1, NULL, 'abcdefghijklmnopqrstuvwxyz'
  UNION ALL
    SELECT
      x + 1,
      SUBSTRING(list FROM 1 FOR 1),
      SUBSTRING(list FROM 2)
    FROM alphabets
    WHERE LENGTH(list) > 0
),
rows(x, row) AS (
  SELECT
    a1.x, 
    STRING_AGG (
      CASE WHEN a2.x IN (ABS(:N / 2 - a1.x), ABS(:N - 1 - ABS(:N / 2 - a1.x))) THEN a1.alphabet ELSE '_' END, 
      '' 
      ORDER BY a2.x
    )
  FROM alphabets a1 CROSS JOIN alphabets a2
  WHERE 0 <= a1.x AND a1.x < :N
  AND   0 <= a2.x AND a2.x < :N
  GROUP BY a1.x
)
SELECT
  CASE WHEN :N % 2 = 0 THEN 'invalid' ELSE STRING_AGG(row, chr(10) ORDER BY x) END AS answer
FROM rows

このSQLをファイルzunda.sqlに保存し、たとえば以下のようにして実行します。psqlコマンドでは-vオプションを使って、バインド変数に値を設定することができるので、これを利用しています。

$ psql -d sandbox -U postgres -v N=24 -f zunda.sql
 answer
---------
 invalid
(1 row)

$ psql -d sandbox -U postgres -v N=25 -f zunda.sql
          answer
---------------------------
 ____________a____________+
 ___________b_b___________+
 __________c___c__________+
 _________d_____d_________+
 ________e_______e________+
 _______f_________f_______+
 ______g___________g______+
 _____h_____________h_____+
 ____i_______________i____+
 ___j_________________j___+
 __k___________________k__+
 _l_____________________l_+
 m_______________________m+
 _n_____________________n_+
 __o___________________o__+
 ___p_________________p___+
 ____q_______________q____+
 _____r_____________r_____+
 ______s___________s______+
 _______t_________t_______+
 ________u_______u________+
 _________v_____v_________+
 __________w___w__________+
 ___________x_x___________+
 ____________y____________
(1 row)
2
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0