Архив рубрики: Кодинг

«С рождения Бобби пай-мальчиком был»

Увлёкся азартной игрой с государством корпорацией.

Успел выиграть каплю знания — PostgreSQL умеет нативно оперировать множествами, в т.ч. — символов. И получается очень удобно, когда словарный запас иссяк:

select word
from public.nouns
where
char_length(word) = 5
and string_to_array(word, null) @> '{с,о}'
and not string_to_array(word, null) && '{а,к,ц,и,я}'
and word like '__ь'
Читать далее «С рождения Бобби пай-мальчиком был»

План — закон!

Выбирал тут планировщик для периодических заданий по обслуживанию приложения.
С Quartz что-то все устали возиться, ленились отдельную схему под его таблички выделять и кончили тем, что возжелали свежих проблем нового, неизведанного.

И, в том числе:

  • Поддержки работы со множеством узлов в кластере;
  • Поддержки персистентности заданий;
  • Простоты использования;
  • Простоты развертывания.

Конечно — open source с подходящей лицензией. И spring-boot-starter в комплекте — для максимального удовольствия.

Читать далее План — закон!

Java List split

Долго валялось в закладках на SO — и пригодилось, наконец. Обычно — или уже была «в коробке» Guava с Lists.partition(), или — Apache Commons и его ListUtils.partition().

Деление на подмножества (каплю доработано относительно исходника на SO):

Java List split
// https://stackoverflow.com/a/30072617 public static <T> Stream<List<T>> listPartition(@NotNull List<T> source, @Positive int length) { requireNonNull(source, "Source list must not be null"); if (length <= 0) { throw new IllegalArgumentException("Partitions length must be greater than zero"); } int size = source.size(); if (size == 0) { return Stream.empty(); } if (size <= length) { return Stream.of(source); } int fullChunks = (size - 1) / length; return IntStream.range(0, fullChunks + 1) .mapToObj(n -> source.subList(n * length, n == fullChunks ? size : (n + 1) * length)); }
Читать далее Java List split

Advent of Code 2023: Day 4: Scratchcards

Про задачу четвертого дня сказать особенно нечего. По условию — проще третей. По парсингу ввода — проще второй. Решается быстро.

Сразу прикинул, что с использованием примитивов или оборачиванием в типы из стандартной библиотеки — будет портяночно. Поэтому — отдельный класс с логикой:

AoC 2023 Day 4 solution
public class Card { private static final Predicate<String> EMPTY = s -> " ".equals(s) || "".equals(s); Integer cardN, winCnt; Set<Integer> win, have; List<Card> nextCards = new ArrayList<>(); // added for part 2 public Card(String cardN, String[] win, String[] have) { this.cardN = Integer.parseInt(cardN.replaceAll("^Card\\s+", "")); this.win = parseNums(win); this.have = parseNums(have); this.winCnt = (int) this.have.stream().filter(h -> this.win.contains(h)).count(); } void addNext(List<Card> nextCards) { // added for part 2 this.nextCards.addAll(nextCards); } Stream<Card> flat() { // added for part 2 return Stream.concat(Stream.of(this), this.nextCards.stream().flatMap(Card::flat)); } private static Set<Integer> parseNums(String[] nums) { return Arrays.stream(nums).filter(not(EMPTY)).map(Integer::parseInt) .collect(Collectors.toSet()); } };
Читать далее Advent of Code 2023: Day 4: Scratchcards

Advent of Code 2023: Day 3: Gear Ratios

В начале была лень… Стойкое нежелание возиться с границами массивов. Оно, и только оно толкнуло меня на скользкую дорожку замены матрицы примитивов на List<List<>>.

Следующим шагом на пути окунания в пучины многословия — стало создание контейнеров для упаковки данных со «схемы двигателя». Вот они:

AoC 2023 Day 3 solution
public record Coord(Integer row, Integer column){}; public record Cell(Coord coord, Integer codePoint){ Set<Coord> border() {return Set.of( new Coord(coord.row(), coord.column() - 1), // left new Coord(coord.row() - 1, coord.column() - 1), // top-left new Coord(coord.row() - 1, coord.column()), // top new Coord(coord.row() - 1, coord.column() + 1), // top-right new Coord(coord.row(), coord.column() + 1), // right new Coord(coord.row() + 1, coord.column() + 1), // bot-right new Coord(coord.row() + 1, coord.column()), // bottom new Coord(coord.row() + 1, coord.column() - 1) // bot-left );} }; public record Part(List<Cell> cells){ public Part { cells = List.copyOf(cells); } Set<Coord> border() { return cells.stream() .flatMap(c -> c.border().stream()) .filter(bCoord -> cells.stream() .noneMatch(c -> bCoord.equals(c.coord()))) .collect(Collectors.toSet()); } Integer value() { return Integer.parseInt(cells.stream() .map(c -> Character.toChars(c.codePoint())) .map(String::new).collect(Collectors.joining())); } };
Читать далее Advent of Code 2023: Day 3: Gear Ratios

Advent of Code 2023: Day 2: Cube Conundrum

Страшный, длинный, мучительный парсинг ввода…
Хотелось бы, конечно, иметь возможность сделать по-перловому, что-то типа: echo -e "Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green\nGame 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue" | perl -wlne '@matches = $_ =~ /(?:\G(?!\A)|^Game) (\S+)/g; print join("=",@matches)'.

Немного почистить после, или сразу докрутить регулярку, чтобы не захватывала разделители. Сложить в хэш. И закончить кучей циклов в итоге 🙁

С другой стороны — и возня с java Matcher не вдохновляла, и описывать структуру в виде POJO — для чисто скриптового решения — зачем.

split — дёшево и сердито, fastpath бонусом. К счастью — ввод был одинаков для обеих частей загадки.

Читать далее Advent of Code 2023: Day 2: Cube Conundrum

Advent of Code 2023: Day 1: Trebuchet?!

Снова AoC — и снова начат с опозданием. Дуплет! Основная идея прежняя — решать в jshell, пока это не станет слишком многословным. Экономия на буковках, в общем.

Обвязка для загрузки условий задачи — та же, что для AoC-2022. Тег для задачек 2023 года — adventofcode-2023 (или раздел Problem Solving).

Читать далее Advent of Code 2023: Day 1: Trebuchet?!

Spring: TLS/SSL подключение к RabbitMQ

Возникла потребность подключаться из Java приложения к брокеру RabbitMQ с использованием защищенного соединения. Приложение на Spring Boot, живёт в контейнере Docker и должно слушать два узла Rabbit параллельно.

  • На входе: сертификат клиентского узла — контейнер client-cert.pfx, корневой сертификат для него root-cert.crt
  • Открытый серверный сертификат шлюза Rabbit: выкачивается автоматически (можно подложить вручную)
  • Используемая версия java поддерживает форматы хранилищ и JKS, и PKCS12
  • Требуется: создать и положить сертификаты в Key Store (сертификаты приложения «клиентские») и Trust Store (доверенные «серверные» сертификаты). В чём разница.
Читать далее Spring: TLS/SSL подключение к RabbitMQ