Skip to content

Instantly share code, notes, and snippets.

@jihchi
Last active October 7, 2025 17:58
Show Gist options
  • Select an option

  • Save jihchi/2d993c308031cf848c404acd06bf0f8a to your computer and use it in GitHub Desktop.

Select an option

Save jihchi/2d993c308031cf848c404acd06bf0f8a to your computer and use it in GitHub Desktop.

Revisions

  1. jihchi revised this gist Oct 7, 2025. 1 changed file with 58 additions and 79 deletions.
    137 changes: 58 additions & 79 deletions solve.ts
    Original file line number Diff line number Diff line change
    @@ -1,85 +1,64 @@
    import { assertArrayIncludes } from "jsr:@std/[email protected]";
    const MIN = 60 * 1000;

    Deno.test(function testGroupChangelogEdits() {
    const MIN = 60 * 1000;
    const groupChangelogEdits = (
    edits: { timestamp: string; component: string }[],
    ) => {
    const map = edits.reduce<Map<string, Date[]>>(
    (acc, { component, timestamp }) => {
    if (!acc.has(component)) {
    acc.set(component, []);
    }
    acc.get(component)?.push(new Date(timestamp));
    return acc;
    },
    new Map(),
    );

    const groupChangelogEdits = (
    edits: { timestamp: string; component: string }[],
    ) => {
    const map = edits.reduce<Map<string, Date[]>>(
    (acc, { component, timestamp }) => {
    if (!acc.has(component)) {
    acc.set(component, []);
    }
    acc.get(component)?.push(new Date(timestamp));
    return acc;
    },
    new Map(),
    );
    for (const [_component, dates] of map) {
    dates.sort();
    }

    for (const [_component, dates] of map) {
    dates.sort();
    }
    return Array.from(map.keys())
    .flatMap((component) => {
    const [firstDate, ...dates] = map.get(component) ?? [];
    const grouped = [
    {
    component,
    start: firstDate,
    end: firstDate,
    },
    ];
    let windowEnd = new Date(firstDate.getTime() + 10 * MIN);

    return Array.from(map.keys())
    .flatMap((component) => {
    const [firstDate, ...dates] = map.get(component) ?? [];
    const grouped = [
    {
    component,
    start: firstDate,
    end: firstDate,
    },
    ];
    let windowEnd = new Date(firstDate.getTime() + 10 * MIN);
    for (const date of dates) {
    if (date > windowEnd) {
    windowEnd = new Date(date.getTime() + 10 * MIN);
    grouped.push({
    component,
    start: date,
    end: date,
    });
    } else {
    const prev = grouped[grouped.length - 1];
    prev.end = new Date(Math.max(prev.end.getTime(), date.getTime()));
    }
    }

    for (const date of dates) {
    if (date > windowEnd) {
    windowEnd = new Date(date.getTime() + 10 * MIN);
    grouped.push({
    component,
    start: date,
    end: date,
    });
    } else {
    const prev = grouped[grouped.length - 1];
    prev.end = new Date(Math.max(prev.end.getTime(), date.getTime()));
    }
    }
    return grouped;
    })
    .map(({ component, start, end }) => ({
    component,
    start: start.toISOString().split(".")[0] + "Z",
    end: end.toISOString().split(".")[0] + "Z",
    }));
    };

    return grouped;
    })
    .map(({ component, start, end }) => ({
    component,
    start: start.toISOString().split(".")[0] + "Z",
    end: end.toISOString().split(".")[0] + "Z",
    }));
    };

    assertArrayIncludes(
    groupChangelogEdits([
    { timestamp: "2025-10-06T08:20:00Z", component: "Header" },
    { timestamp: "2025-10-06T08:05:00Z", component: "Header" },
    { timestamp: "2025-10-06T08:00:00Z", component: "Header" },
    { timestamp: "2025-10-06T08:15:00Z", component: "Footer" },
    { timestamp: "2025-10-06T08:07:00Z", component: "Footer" },
    ]),
    [
    {
    component: "Footer",
    start: "2025-10-06T08:07:00Z",
    end: "2025-10-06T08:15:00Z",
    },
    {
    component: "Header",
    start: "2025-10-06T08:00:00Z",
    end: "2025-10-06T08:05:00Z",
    },
    {
    component: "Header",
    start: "2025-10-06T08:20:00Z",
    end: "2025-10-06T08:20:00Z",
    },
    ],
    );
    });
    console.log(
    groupChangelogEdits([
    { timestamp: "2025-10-06T08:20:00Z", component: "Header" },
    { timestamp: "2025-10-06T08:05:00Z", component: "Header" },
    { timestamp: "2025-10-06T08:00:00Z", component: "Header" },
    { timestamp: "2025-10-06T08:15:00Z", component: "Footer" },
    { timestamp: "2025-10-06T08:07:00Z", component: "Footer" },
    ]),
    );
  2. jihchi revised this gist Oct 7, 2025. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion solve.ts
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    import { assertArrayIncludes } from "@std/assert";
    import { assertArrayIncludes } from "jsr:@std/assert@1.0.15";

    Deno.test(function testGroupChangelogEdits() {
    const MIN = 60 * 1000;
  3. jihchi revised this gist Oct 7, 2025. 1 changed file with 5 additions and 0 deletions.
    5 changes: 5 additions & 0 deletions _README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,5 @@
    Deno v2.5.3

    ```sh
    deno run https://gist.github.com/jihchi/2d993c308031cf848c404acd06bf0f8a/raw/solve.ts
    ```
  4. jihchi created this gist Oct 7, 2025.
    85 changes: 85 additions & 0 deletions solve.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,85 @@
    import { assertArrayIncludes } from "@std/assert";

    Deno.test(function testGroupChangelogEdits() {
    const MIN = 60 * 1000;

    const groupChangelogEdits = (
    edits: { timestamp: string; component: string }[],
    ) => {
    const map = edits.reduce<Map<string, Date[]>>(
    (acc, { component, timestamp }) => {
    if (!acc.has(component)) {
    acc.set(component, []);
    }
    acc.get(component)?.push(new Date(timestamp));
    return acc;
    },
    new Map(),
    );

    for (const [_component, dates] of map) {
    dates.sort();
    }

    return Array.from(map.keys())
    .flatMap((component) => {
    const [firstDate, ...dates] = map.get(component) ?? [];
    const grouped = [
    {
    component,
    start: firstDate,
    end: firstDate,
    },
    ];
    let windowEnd = new Date(firstDate.getTime() + 10 * MIN);

    for (const date of dates) {
    if (date > windowEnd) {
    windowEnd = new Date(date.getTime() + 10 * MIN);
    grouped.push({
    component,
    start: date,
    end: date,
    });
    } else {
    const prev = grouped[grouped.length - 1];
    prev.end = new Date(Math.max(prev.end.getTime(), date.getTime()));
    }
    }

    return grouped;
    })
    .map(({ component, start, end }) => ({
    component,
    start: start.toISOString().split(".")[0] + "Z",
    end: end.toISOString().split(".")[0] + "Z",
    }));
    };

    assertArrayIncludes(
    groupChangelogEdits([
    { timestamp: "2025-10-06T08:20:00Z", component: "Header" },
    { timestamp: "2025-10-06T08:05:00Z", component: "Header" },
    { timestamp: "2025-10-06T08:00:00Z", component: "Header" },
    { timestamp: "2025-10-06T08:15:00Z", component: "Footer" },
    { timestamp: "2025-10-06T08:07:00Z", component: "Footer" },
    ]),
    [
    {
    component: "Footer",
    start: "2025-10-06T08:07:00Z",
    end: "2025-10-06T08:15:00Z",
    },
    {
    component: "Header",
    start: "2025-10-06T08:00:00Z",
    end: "2025-10-06T08:05:00Z",
    },
    {
    component: "Header",
    start: "2025-10-06T08:20:00Z",
    end: "2025-10-06T08:20:00Z",
    },
    ],
    );
    });