以ä¸ã®ãããªãã¤ã¼ããè¦ããã¦ãAtCoderã§SQLã使ãããã¨ãããã£ãã®ã§è©¦ãã« AtCoder Beginners Selection ã®åé¡ãå¯è½ãªéãSQLã使ã£ã¦è§£ãã¦ã¿ã¾ãããã§ããã ãæ¨æºå ¥åºåãPythonå´ã§è¡ã£ã¦ããã®ä»ã®è¨ç®ãSQLiteå´ã§è¡ãã¾ã
æ¨æ¥ã®Dåé¡ã§Pythonã ã¨è§£ããªãã¨åãã¦ããçããã
— zat (@zat22859390) 2021å¹´9æ5æ¥
Pythonã®ç¹æ¨©ãSQLã§è§£ãã¨ããæãããã¾ããã
AtCoderã§SQLã使ããã®ã¯Python/PyPyã ãï¼https://t.co/S3aCbGNhti
zenn.dev
PracticeA - Welcome to AtCoder
æ¨æºå
¥åºåããèªã¿åã£ãæ°å¤ã足ãã¦ãæååã¯ãã®ã¾ã¾åºåãã¾ãã
SQLã¯ã¨ãªãä½ãã¨ãã«ãå¤æ°ãæååçµåã§ãã£ã¤ãã¦ãã®ã¯ä¸è¬çã«ã¯ãã¾ããããªãæ°ããã¾ãããä»åã®ç¨éã§ã¯ç¹ã«åé¡ãªãã¨æãã®ã§ãã®è¨äºä¸ã§ã¯æ°ã«ãã使ã£ã¦ããã¾ãã
import sqlite3 con = sqlite3.connect(":memory:", isolation_level=None) cur = con.cursor() cur.executescript(""" PRAGMA trusted_schema = OFF; PRAGMA journal_mode = OFF; PRAGMA synchronous = OFF; PRAGMA temp_store = memory; PRAGMA secure_delete = OFF; """) a = input() b, c = input().split() s = input() for i in cur.execute(f""" SELECT {a} + {b} + {c}, "{s}" """): print(*i)
ABC086A - Product
2ã¤ã®æ´æ°ããããçµæãå¶æ°ãã©ãããçãã¾ãã
æ¡ä»¶åå²ã¯ CASEå¼ã使ã£ã¦ CASE WHEN æ¡ä»¶ THEN å¤ CASE æ¡ä»¶2 THEN å¤2 ç¥ ELSE ãã®ä»ã®å ´åã®å¤ END
ã®ããã«æ¸ãã¾ã
import sqlite3 con = sqlite3.connect(":memory:", isolation_level=None) cur = con.cursor() cur.executescript(""" PRAGMA trusted_schema = OFF; PRAGMA journal_mode = OFF; PRAGMA synchronous = OFF; PRAGMA temp_store = memory; PRAGMA secure_delete = OFF; """) a, b = map(int, input().split()) for i in cur.execute(f"SELECT CASE WHEN {a} * {b} % 2 = 0 THEN \"Even\" ELSE \"Odd\" END"): print(i[0])
ABC081A - Placing Marbles
0ã¨1ã§æ§æããã3æåã®æååã«å«ã¾ãã1ã®åæ°ãæ±ããã°è¯ãã§ã
ããããã¨ããããã¯ããã¨æãã¾ãããREPLACEã§0ãæ¶ãã¦1ã ãã«ãªã£ãæååã®é·ããè¿ãã¾ãã
import sqlite3 con = sqlite3.connect(":memory:", isolation_level=None) cur = con.cursor() cur.executescript(""" PRAGMA trusted_schema = OFF; PRAGMA journal_mode = OFF; PRAGMA synchronous = OFF; PRAGMA temp_store = memory; PRAGMA secure_delete = OFF; """) s = input() for i in cur.execute(f"SELECT LENGTH(REPLACE({s}, \"0\", \"\"))"): print(i[0])
ABC081B - Shift only
ä¸ããããè¤æ°ã®æ´æ°ããã¹ã¦å²ãåããæ大㮠\(2^k\) ã® \(k\) ãåçãã¾ãã
CASEå¼ã使ã£ã¦ä¸ããi+1ãããç®ã1ãªãiãè¿ãã¦ããã§ãªããªãé©å½ãªå¤§ããªå¤ãè¿ãå¤å®ãä½ãã¾ãã
é¢åãªã®ã§åãããã«ã¤ãã¦Pythonå´ã§çæããã¨ãããªæãã§ãã
cases = ",\n".join([f"CASE WHEN (1 << {i}) & n THEN {i} ELSE 10000 END" for i in range(0, 30)])
ããæ°ã«ã¤ãã¦å¿
è¦ãªãã¹ã¦ã®ãããã«å¯¾ãã¦ä¸ã®å¤å®ããã¦è¤æ°å¼æ°ã®å ´åã®MINé¢æ°ã§æå°å¤ãåãã°ããã®æ°ãå²ãåããç®æããããã¾ãã
Built-In Scalar SQL Functions
ãã¨ã¯ãã®çµæã«ã¤ãã¦éè¨é¢æ°ã®æ¹ã®MINé¢æ°ã§ãã¹ã¦ã®æ°ã«ã¤ãã¦éè¨ããªããã°ãã¹ã¦ã®æ´æ°ãå²ãåããå¤ããããã¾ã
import sqlite3 con = sqlite3.connect(":memory:", isolation_level=None) cur = con.cursor() cur.executescript(""" PRAGMA trusted_schema = OFF; PRAGMA journal_mode = OFF; PRAGMA synchronous = OFF; PRAGMA temp_store = memory; PRAGMA secure_delete = OFF; CREATE TABLE num(n INTEGER); """) N = input() A = map(int, input().split()) cur.executemany("INSERT INTO num VALUES(?)", map(lambda x: (x,), A)) cases = ",\n".join([f"CASE WHEN (1 << {i}) & n THEN {i} ELSE 10000 END" for i in range(0, 30)]) for i in cur.execute(f""" SELECT MIN( MIN( {cases} ) ) FROM num """): print(i[0])
ABC087B - Coins
500åçãAæã100åçãBæã50åçãCæããã¨ãã«ãåè¨Xåã«ããæ¹æ³ãçãã¾ã
500åçã0ããAæã100åçã0ããBæã50åçã0ããCæããæã®çµã¿åããã®ç·å½ãã試ãã¦å¤å®ããã°ããã§ãã
SQLã ã¨foræããªãã®ã§ã0, 1, 2, ..., Aãªã©ã®æ°åãçæãã¦ããJOINãã¦è¨ç®ãã¾ãã
SQLiteã ã¨æ´æ°åã®çæããã¦ããããããªé¢æ°ããªããããªã®ã§ãWITH RECURSIVE
ã使ã£ã¦æ´æ°åãçæãã¾ãã
WITH RECURSIVE
ã¯æåã«ãã¼ã¿ãçæãã¦ããã以éã¯çæããããã¼ã¿ã«å¯¾ãã¦ããå¦çããã¦ãæ´ã«çæãããåãå¦çããã¦ãã¨ããã®ãç¹°ãè¿ãã¦ãã¼ã¿ãçæãã¦ããã¾ãã
ä¾ãã°ä»¥ä¸ã®ä¾ã ã¨ãæåã«0ã®è¡ãçæãã¦ãããã«+1ãã¦1ã®è¡ãçæããã¦ã1ã«å¯¾ãã¦+1ãã¦2ã®è¡ãçæããã¦â¦â¦ã¨ããæãã§ãã¼ã¿ãçæãã¦ããã¾ããWHEREã®æ¡ä»¶ã«å¼ã£ããã£ã¦æ¬¡ã®è¡ãçæãããªããªã£ããçµäºãã¾ãã
WITH RECURSIVE coin500(i) AS ( SELECT 0 UNION SELECT i + 1 FROM coin500 WHERE i + 1 <= {A} )
å ¨ä½ã®ã³ã¼ã
import sqlite3 con = sqlite3.connect(":memory:", isolation_level=None) cur = con.cursor() cur.executescript(""" PRAGMA trusted_schema = OFF; PRAGMA journal_mode = OFF; PRAGMA synchronous = OFF; PRAGMA temp_store = memory; PRAGMA secure_delete = OFF; """) A = input() B = input() C = input() X = input() for i in cur.execute(f""" WITH RECURSIVE coin500(i) AS ( SELECT 0 UNION SELECT i + 1 FROM coin500 WHERE i + 1 <= {A} ), coin100(i) AS ( SELECT 0 UNION SELECT i + 1 FROM coin100 WHERE i + 1 <= {B} ), coin50(i) AS ( SELECT 0 UNION SELECT i + 1 FROM coin50 WHERE i + 1 <= {C} ) SELECT COUNT(*) FROM coin500, coin100, coin50 WHERE coin500.i * 500 + coin100.i * 100 + coin50.i * 50 = {X} """): print(i[0])
ABC083B - Some Sums
1以ä¸N以ä¸ã®æ´æ°ã®ãã¡10é²æ³ã§ã®åæ¡ã®æ°åã®åè¨ãA以ä¸B以ä¸ã§ããæ°ã®ç·åãçãã¾ãã
10000, 1000, 100, 10, 1ã§å²ã£ãåã10ã§å²ã£ãä½ããæ±ããã°åæ¡ã®æ°åãæ±ãããã¾ãã
ãã¨ã¯1ããNã¾ã§ã®å¤ã WITH RECURSIVE ã§çæãã¦æ¡ä»¶ãæºããå¤ã®åè¨ãè¨ç®ããã ãã§ãã
%%bash echo ' import sqlite3 con = sqlite3.connect(":memory:", isolation_level=None) cur = con.cursor() cur.executescript(""" PRAGMA trusted_schema = OFF; PRAGMA journal_mode = OFF; PRAGMA synchronous = OFF; PRAGMA temp_store = memory; PRAGMA secure_delete = OFF; """) N, A, B = map(int, input().split()) for i in cur.execute(f""" WITH RECURSIVE seq(n) AS ( SELECT 1 UNION SELECT n + 1 FROM seq WHERE n + 1 <= {N} ) SELECT SUM(n) FROM seq WHERE CAST(n / 10000 AS INTEGER) % 10 + CAST(n / 1000 AS INTEGER) % 10 + CAST(n / 100 AS INTEGER) % 10 + CAST(n / 10 AS INTEGER) % 10 + CAST(n / 1 AS INTEGER) % 10 BETWEEN {A} AND {B} """): print(i[0]) ' > main.py echo "100 4 16" > input.txt cat input.txt | python main.py
ABC088B - Card Game for Two
ä¸ããããæ´æ°ã大ããé ã«ã½ã¼ããã¦ãæ大ã®ãã®ããé ã«1çªç®ã2çªãâ¦ã¨ããã¨ãã«ãå¥æ°çªç®ã®åè¨ããå¶æ°çªç®ã®åè¨ãå¼ãã¦çããã°ããã§ãã
以ä¸ã®ããã«ã¦ã£ã³ãã¦é¢æ°ã使ããã°ç°¡åã«æ±ããããã®ã§ããSQLiteã®ãã¼ã¸ã§ã³ãå¤ãã®ããã©ããæ¸ãééããã®ã使ããªãã£ãã§ãã
SELECT SUM(CASE WHEN row_num % 2 = 1 THEN n ELSE 0 END) - SUM(CASE WHEN row_num % 2 = 0 THEN n ELSE 0 END) FROM ( SELECT n, ROW_NUMBER() OVER (ORDER BY n DESC) AS row_num FROM num )
ãªã®ã§ä¸åº¦ãã¼ãã«ã«ä¿åãã¦ããè¨ç®ãã¾ãããSQLiteã§ã¯ããã©ã«ãã§ã¯ããã¼ãã«ã«è¡ãä¿åããã¨rowidã¨ãã1ããé ã®IDãæé»çã«æ¯ãããã®ã§ãã½ã¼ãæ¸ã¿ã®å¤ããã¼ãã«ã«ä¿åãã¦rowidã®å¶å¥ãè¦ã¦è¨ç®ãã¾ãã
import sqlite3 con = sqlite3.connect(":memory:", isolation_level=None) cur = con.cursor() cur.executescript(""" PRAGMA trusted_schema = OFF; PRAGMA journal_mode = OFF; PRAGMA synchronous = OFF; PRAGMA temp_store = memory; PRAGMA secure_delete = OFF; CREATE TABLE num(n INTEGER); """) N = input() A = map(int, input().split()) cur.executemany("INSERT INTO num VALUES(?)", map(lambda x: (x,), A)) cur.execute(f""" CREATE TEMPORARY TABLE ordered AS SELECT n FROM num ORDER BY n DESC """) for i in cur.execute(f""" SELECT (SELECT SUM(n) FROM ordered WHERE rowid % 2 = 1) - (SELECT SUM(n) FROM ordered WHERE rowid % 2 = 0) """): print(i[0])
ABC085B - Kagami Mochi
ä¸ããããè¤æ°ã®æ´æ°ã®ãã¡ã¦ãã¼ã¯ãªåæ°ãçããã°ããã§ãã
SQLã§ã¯ COUNT(DISTINCT) ããã ããªã®ã§ç°¡åã§ã
import sqlite3 con = sqlite3.connect(":memory:", isolation_level=None) cur = con.cursor() cur.executescript(""" PRAGMA trusted_schema = OFF; PRAGMA journal_mode = OFF; PRAGMA synchronous = OFF; PRAGMA temp_store = memory; PRAGMA secure_delete = OFF; CREATE TABLE num(n INTEGER); """) N = int(input()) D = [] for i in range(N): D.append(input()) cur.executemany("INSERT INTO num VALUES(?)", map(lambda x: (x,), D)) for i in cur.execute(f""" SELECT COUNT(DISTINCT n) FROM num """): print(i[0])
ABC085C - Otoshidama
10000åæã5000åæã1000åæãåè¨Næ使ã£ã¦åè¨Yåã«ãªãçµã¿åãããä¸ã¤çãã¾ãã
10000åæã5000åæã®ææ°åè£ãçæãã¦JOINãã¦ãæ®ãéé¡ã1000åæã§è£ã£ãå ´åã«æ¡ä»¶ãæºãããå¤å®ã
import sqlite3 con = sqlite3.connect(":memory:", isolation_level=None) cur = con.cursor() cur.executescript(""" PRAGMA trusted_schema = OFF; PRAGMA journal_mode = OFF; PRAGMA synchronous = OFF; PRAGMA temp_store = memory; PRAGMA secure_delete = OFF; """) N, Y = map(int, input().split()) result = list(cur.execute(f""" WITH RECURSIVE money10000(i) AS ( SELECT 0 UNION SELECT i + 1 FROM money10000 WHERE i + 1 <= {Y} / 10000 ), money5000(i) AS ( SELECT 0 UNION SELECT i + 1 FROM money5000 WHERE i + 1 <= {Y} / 5000 ) SELECT money10000.i, money5000.i, ({Y} - money10000.i * 10000 - money5000.i * 5000) / 1000 FROM money10000, money5000 WHERE ({Y} - money10000.i * 10000 - money5000.i * 5000) % 1000 = 0 AND ({Y} - money10000.i * 10000 - money5000.i * 5000) / 1000 >= 0 AND money10000.i + money5000.i + ({Y} - money10000.i * 10000 - money5000.i * 5000) / 1000 = {N} """)) if result: print(*result[0]) else: print(-1, -1, -1)
ABC049C - Daydream
ä¸ããããæååã®æ«å°¾ãã貪欲ã«"dream", "dreamer", "erase", "eraser"ã®æååãå¯è½ãªéãåãé¤ãã¦ãã£ã¦ãæçµçã«ç©ºæååã«ãªããã©ãããå¤å®ãã¾ãã
REGEXPã使ã£ã¦æ£è¦è¡¨ç¾ã§å¤å®ããã°ä¸ç¬ã ã¨æã£ãã®ã§ãããSQLiteã®ãã¼ã¸ã§ã³ãå¤ãã¦ä½¿ããªãã£ãã§ãã
WITH RECURSIVEã使ã£ã¦ãæ«å°¾ããæååãåãé¤ããæååãé ã«çæãã¦ããã¯ã¨ãªãæ¸ããã®ã§ãããããã¯TLEã«ãªã£ã¦ãã¾ãã¾ããã
import sqlite3 con = sqlite3.connect(":memory:", isolation_level=None) cur = con.cursor() cur.executescript(""" PRAGMA trusted_schema = OFF; PRAGMA journal_mode = OFF; PRAGMA synchronous = OFF; PRAGMA temp_store = memory; PRAGMA secure_delete = OFF; """) S = input() for i in cur.execute(f""" WITH RECURSIVE str(s) AS ( SELECT "{S}" UNION SELECT CASE WHEN substr(s, -5) = "dream" THEN substr(s, 1, length(s) - 5) WHEN substr(s, -7) = "dreamer" THEN substr(s, 1, length(s) - 7) WHEN substr(s, -5) = "erase" THEN substr(s, 1, length(s) - 5) WHEN substr(s, -6) = "eraser" THEN substr(s, 1, length(s) - 6) END FROM str WHERE s IS NOT NULL ) SELECT CASE WHEN COUNT(*) = 1 THEN "YES" ELSE "NO" END FROM str WHERE s = "" """): print(i[0])
æçµæ段ã¨ãã¦SQLã§ãã¹ã¦ããã®ã¯è«¦ãã¦æ£è¦è¡¨ç¾ã¯ã¦ã¼ã¶ã¼å®ç¾©é¢æ°ã§å¤å®ãããã¨ã«ãã¾ããã
SQLiteã§ã¯Pythonå´ã§å®ç¾©ããé¢æ°ãSQLããå¼ã³åºããã¨ãã§ãã¾ãã
以ä¸ã®ããã«Pythonã®é¢æ°ãcreate_functionã§æ¸¡ãã°SQLä¸ãã使ããã¨ãã§ãã¾ã
def re_match(s: str): return re.match("^(dream|dreamer|erase|eraser)+$", s) is not None con.create_function("RE_MATCH", 1, re_match) S = input() cur.execute(f""" SELECT CASE WHEN RE_MATCH("{S}") = 1 THEN "YES" ELSE "NO" END """)
å ¨ä½ã®ã³ã¼ã
import sqlite3 import re con = sqlite3.connect(":memory:", isolation_level=None) cur = con.cursor() cur.executescript(""" PRAGMA trusted_schema = OFF; PRAGMA journal_mode = OFF; PRAGMA synchronous = OFF; PRAGMA temp_store = memory; PRAGMA secure_delete = OFF; """) # SQLiteã®ãã¼ã¸ã§ã³ãæ°ãããã°REGEXPã§æ£è¦è¡¨ç¾ã使ããã¯ãã ãã©ä½¿ããªãã®ã§å¦¥å def re_match(s: str): return re.match("^(dream|dreamer|erase|eraser)+$", s) is not None con.create_function("RE_MATCH", 1, re_match) S = input() for i in cur.execute(f""" SELECT CASE WHEN RE_MATCH("{S}") = 1 THEN "YES" ELSE "NO" END """): print(i[0])
ABC086C - Traveling
æå»ã1é²ããã¨ã«x軸æ¹åãy軸æ¹åã«1移åããã
x, y = 0, 0ããã¹ã¿ã¼ãããã¨ãã¦ãæå»ã¨ãã®ã¨ãã®x, y座æ¨ã®çµã¿åãããè¤æ°ä¸ããããã®ã§æå¾ã¾ã§ç§»åå¯è½ããçããã
æå»ã®å·®ããã³ããã¿ã³è·é¢ããã大ãããã¨ã¨ãæå»ã®å·®ã®å¶å¥ã¨ãã³ããã¿ã³è·é¢ã®å¶å¥ãä¸è´ãã¦ããã°ãã(åãç®æã§åå¾ç§»åãç¹°ãè¿ãã°2ãã¤æ¶è²»ã§ãã)
import sqlite3 con = sqlite3.connect(":memory:", isolation_level=None) cur = con.cursor() cur.executescript(""" PRAGMA trusted_schema = OFF; PRAGMA journal_mode = OFF; PRAGMA synchronous = OFF; PRAGMA temp_store = memory; PRAGMA secure_delete = OFF; CREATE TABLE points(t INTEGER, x INTEGER, y INTEGER); """) N = int(input()) data = [] for i in range(N): data.append(input().split()) cur.execute("INSERT INTO points VALUES(?, ?, ?)", (0, 0, 0)) cur.executemany("INSERT INTO points VALUES(?, ?, ?)", data) for i in cur.execute(f""" SELECT CASE WHEN ( SELECT COUNT(*) FROM points AS current JOIN points AS next ON current.rowid = next.rowid - 1 WHERE NOT ( ABS(current.x - next.x) + ABS(current.y - next.y) <= (next.t - current.t) AND (ABS(current.x - next.x) + ABS(current.y - next.y)) % 2 = (next.t - current.t) % 2 ) ) > 0 THEN "No" ELSE "Yes" END """): print(i[0])
ã¾ã¨ã
ãµã¯ãã¨ã§ãããã¨æãã¾ãããçµæ§ã¤ããã£ãã§ãããã¯ãforã«ã¼ãçãªãã®ãæ°è»½ã«ãããªãã®ã¯ãªããªã大å¤ã
ãã¨ã¯SQLiteã®ãã¼ã¸ã§ã³ãå¤ãã¦ã¦ã£ã³ãã¦é¢æ°ãæ£è¦è¡¨ç¾ã使ããªãã£ãã®ãè¦å´ãã¾ããã
SQLiteã«è§¦ãã®ã¯ã»ã¨ãã©åãã¦ã ã£ãã®ã§ããæ§æã®èª¬æãªã©ã®ããã¥ã¡ã³ããé£ããã£ãã§ã
www.sqlite.org