package puzzle; import module java.base; import module java.sql; public final class ScoreHintsTask { public static void main(String[] args) throws Exception { Class.forName("org.sqlite.JDBC"); try (Connection conn = DriverManager.getConnection("jdbc:sqlite:tools/hint/hint.sqlite")) { updateCrossScores(conn, ScoreHintsTask::crossabilityScore, 1000); } } static final Map LETTER_WEIGHT = Map.ofEntries( Map.entry('E', 10), Map.entry('N', 9), Map.entry('A', 9), Map.entry('R', 8), Map.entry('I', 8), Map.entry('O', 7), Map.entry('S', 7), Map.entry('T', 7), Map.entry('D', 6), Map.entry('L', 6), Map.entry('K', 5), Map.entry('M', 5), Map.entry('U', 5), Map.entry('P', 4), Map.entry('G', 4), Map.entry('H', 4), Map.entry('V', 4), Map.entry('B', 3), Map.entry('W', 3), Map.entry('C', 2), Map.entry('F', 2), Map.entry('Z', 2), Map.entry('J', 1), Map.entry('Y', 1), Map.entry('Q', 0), Map.entry('X', 0) ); static boolean isVowel(char ch) { return ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U'; } static int crossabilityScore(String w) { var score = 0; var vowels = 0; for (var i = 0; i < w.length(); i++) { var ch = w.charAt(i); score += LETTER_WEIGHT.getOrDefault(ch, 2); if (isVowel(ch)) vowels++; } var ratio = vowels / (double) w.length(); if (ratio >= 0.35 && ratio <= 0.65) score += 8; if (w.indexOf('Q') >= 0 || w.indexOf('X') >= 0) score -= 6; if (w.indexOf('Y') >= 0 || w.indexOf('J') >= 0) score -= 2; return score; } /** * Updates hints.cross_score by computing a score from hints.word. * * @param conn open JDBC connection (PostgreSQL) * @param scoreFn callback: scoreFn.applyAsInt(word) * @param batchSize e.g. 1000 */ public static void updateCrossScores( Connection conn, ToIntFunction scoreFn, int batchSize ) throws SQLException { // Use a transaction for speed + consistency final boolean prevAutoCommit = conn.getAutoCommit(); conn.setAutoCommit(false); // Server-side cursor behavior in pgjdbc requires autoCommit=false + fetchSize>0 final String selectSql = "SELECT id, puzzle_norm " + "FROM hints " + "WHERE puzzle_norm IS NOT NULL"; // optionally add: " AND cross_score IS NULL" final String updateSql = "UPDATE hints SET cross_score = ? WHERE id = ?"; try (PreparedStatement psSel = conn.prepareStatement(selectSql); PreparedStatement psUpd = conn.prepareStatement(updateSql)) { psSel.setFetchSize(batchSize); int pending = 0; try (ResultSet rs = psSel.executeQuery()) { while (rs.next()) { long id = rs.getLong("id"); String word = rs.getString("puzzle_norm"); int score; try { score = scoreFn.applyAsInt(word); } catch (RuntimeException ex) { ex.printStackTrace(); // If scoring fails, decide your policy: skip or set 0. // Here: skip row. continue; } psUpd.setInt(1, score); psUpd.setLong(2, id); psUpd.addBatch(); pending++; if (pending >= batchSize) { psUpd.executeBatch(); conn.commit(); pending = 0; } } } if (pending > 0) { psUpd.executeBatch(); conn.commit(); } } catch (SQLException e) { conn.rollback(); throw e; } finally { conn.setAutoCommit(prevAutoCommit); } } }