Skip to content

arozanov/pack-calculator

Repository files navigation

Pack Calculator

Solution for the RE Partners coding challenge. Calculates the optimal combination of whole packs for a given order.

Rules

  1. Only whole packs can be sent.
  2. Within rule 1, ship the smallest possible total number of items.
  3. Within rules 1 and 2, use the smallest possible number of packs.

Rule 2 takes precedence over rule 3.

Run with Docker

The single image contains both the Go API and the embedded React UI.

docker compose up --build

Then open http://localhost:8080.

The pack sizes are persisted in a Docker volume, so they survive container restarts.

Run from source

You need Go 1.23+ and Node 20+.

make frontend   # builds the UI into internal/web/dist
make run        # starts the server on :8080

Or for development with hot reload, run the API and the Vite dev server in two terminals:

go run ./cmd/server
cd frontend && npm run dev

The Vite dev server proxies /api/* to the Go server.

Tests

go test ./...

There are unit tests for the algorithm, the storage layer and the HTTP handlers, including the edge case described below.

API

GET /api/pack-sizes

Returns the configured pack sizes.

{"pack_sizes": [250, 500, 1000, 2000, 5000]}

PUT /api/pack-sizes

Replaces the configured pack sizes. Sizes must be positive and unique.

{"pack_sizes": [250, 500, 1000]}

POST /api/calculate

Calculates the optimal pack combination for an order.

{"items": 12001}

Response (packs are sorted by size descending):

{
  "packs": [
    {"size": 5000, "count": 2},
    {"size": 2000, "count": 1},
    {"size": 250, "count": 1}
  ],
  "total_items": 12250,
  "total_packs": 4
}

GET /api/health

Returns {"status":"ok"}.

Algorithm

Greedy doesn't work here -- with packs [23, 31, 53] and order 500000, greedy overshoots but 2*23 + 7*31 + 9429*53 = 500000 exact.

Uses DP: dp[i] = min packs to make exactly i items, -1 if not reachable. Table from 0 to order + max(pack), then scan upward from the order to find the first reachable total. Runs in a couple of ms for the 500k edge case.

Project layout

cmd/server          program entry point
internal/calc       pack calculation algorithm and tests
internal/api        HTTP handlers, middleware, JSON shapes
internal/store      storage interface, in-memory and JSON file impls
internal/web        embed package for the built frontend
frontend            Vite + React UI

The Go binary embeds the built frontend so deployment is a single binary or container.

Configuration

-addr flag or ADDR env var sets the listen address (default :8080). Also picks up PORT if set (Railway, Render, etc).

-data flag or DATA_PATH env var sets the JSON persistence path (default data/pack-sizes.json). Seeded with [250, 500, 1000, 2000, 5000] on first run.

Deployment

Includes a railway.json for Railway. Push to GitHub, create a Railway project from the repo, add a volume on /data, done.

Works on any container host since it's just a single Docker image on port 8080.

About

Pack calculator coding challenge

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors