Pipes and cisterns calculator free online
Two pipes that fill a tank in 4 and 6 hours fill it together in 2.4 hours. Enter how long each inlet takes to fill the tank and each drain to empty it, and get the net rate, the time needed and the status. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Fill pipes (hours each, alone)
- 4, 6
- Net rate (tank fraction per hour)
- 0.4166666667
- Hours to fill
- 2.4
- Status
- Filling
Net fill rate for tanks with inlet pipes and outlet drains, returning hours to fill or empty. Free, deterministic, and private in your browser. No account required.
How pipes and cisterns problems work
These classic problems treat a full tank as one unit of work. A pipe that would fill the tank alone in H hours adds 1/H of the tank every hour, and a drain that would empty it in H hours removes 1/H every hour. Adding all those signed rates gives the net rate. For inlets of 4 and 6 hours the net rate is about 0.4166666667 of the tank per hour, and one divided by that rate gives 2.4 hours to fill. A negative net rate means the tank is emptying, and the same division gives the hours until it is dry.
Reading the result, and the classic trap
The status tells you at a glance whether the tank is filling, emptying or stalled, which happens when inflow and outflow cancel and no progress is made either way. Only the relevant time is given: the hours to fill when it is filling, the hours to empty when it is emptying. The classic trap is adding or averaging the times, for instance treating 4 and 6 hours as 10 or 5; rates add, times do not. List every inlet and every drain the problem has, and keep all the times in the same unit.
How the model works
Classic pipes-and-cisterns problems treat a full tank as one unit of work. Each inlet pipe that would fill the tank alone in H hours contributes a positive rate of one over H tank-fractions per hour. Each outlet or drain that would empty the same full tank in H hours contributes a negative rate of one over H.
The signed net rate decides the outcome: positive means the tank is filling, negative means it is emptying, and a near-zero rate means the system is stalled with no progress either way. You never need a spreadsheet or a CAS; the contract freezes success and error paths for homework, teaching, and automation alike.
What you can do with it
Homework and exams
Check classic quantitative problems quickly with stable, reproducible answers.
Automation
Call the same pure function from scripts without installing a spreadsheet or CAS.
FAQ
Is this free?
Yes. Tier A runs entirely in your browser without an account.
How is a drain handled in the calculation?
As a negative rate. A drain that would empty the full tank in H hours removes 1/H of the tank every hour, and it is added with a minus sign to the inlets to give the net rate.
What does it mean when the tank is stalled?
That what flows in and what flows out cancel each other: the net rate is practically zero and the level moves in neither direction. In that case there is no time to fill or to empty to show.
Can I enter more than two pipes?
Yes. List every inlet and every drain the problem mentions, and the calculator adds up each rate. If one side has a single pipe, entering that one number of hours is enough.
Why are the rates added and not the hours?
Because each pipe contributes a fraction of the tank per hour, and those fractions add up. Adding or averaging the hours, such as treating 4 and 6 as 10 or 5, gives a wrong answer; the right one is 2.4 hours.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/math/pipes-cisterns \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"fill_hours":[1],"empty_hours":[1]}'const res = await fetch("https://api.kit.forhosting.com/math/pipes-cisterns", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"fill_hours": [
1
],
"empty_hours": [
1
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/math/pipes-cisterns",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"fill_hours": [
1
],
"empty_hours": [
1
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/math/pipes-cisterns", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"fill_hours":[1],"empty_hours":[1]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"fill_hours":[1],"empty_hours":[1]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/math/pipes-cisterns", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"fill_hours": [
1
],
"empty_hours": [
1
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "math.pipes_cisterns",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
Pricing starts at $0.002 when you use the API path.
How the model works
You may list several inlets under fill_hours and several outlets under empty_hours; the solver sums every reciprocal. When the net rate is positive, hours_to_fill is one divided by that rate; when negative, hours_to_empty is one divided by the absolute value. This pure arithmetic is fully deterministic and runs free in the browser with the same pure function as the API path. Inputs are validated before any arithmetic so wrong types and out-of-range values become clear invalid_input errors instead of silent NaN results.
Inputs and outputs
A single number is accepted and wrapped as a one-element list for convenience. At least one of the two fields must be present with at least one entry; an empty request is rejected early. Error messages use stable English match substrings for the harness. Provide fill_hours and empty_hours as arrays of positive numbers, or omit one side if only inlets or only outlets apply. On success the payload always includes net_rate_per_hour, hours_to_fill, hours_to_empty, and status so clients can bind UI metrics without guessing field names. status is filling, emptying, or stalled. hours_to_fill is null when the tank is not filling; hours_to_empty is null when it is not emptying. The implementation is fully deterministic and runs free in the browser with the same pure function as the API path. Inputs are validated before any arithmetic so wrong types and out-of-range values become clear invalid_input errors instead of silent NaN results.
Edge cases and limits
Every hour value must be a finite number strictly greater than zero; zero, negative, or non-numeric entries fail with invalid_input. Equal opposing rates return status stalled with net_rate_per_hour zero and both hour fields null, without dividing by zero. Extremely large intermediate values that overflow IEEE-754 become an out-of-range error rather than null fields. The implementation is fully deterministic and runs free in the browser with the same pure function as the API path. Inputs are validated before any arithmetic so wrong types and out-of-range values become clear invalid_input errors instead of silent NaN results.
Integration use cases
Teaching demos
Show worked examples with golden fixtures that match the free widget and the API.
Technical questions
Does it call the network?
No. The parse engine keeps everything on-device in the free widget.
What if my input is invalid?
You receive invalid_input with a clear English message.
Are results stable?
Yes. Deterministic math and golden examples freeze the contract.
Who authors this capacity?
abuela on the ForHosting KIT workshop.