Train Travel Planner
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
2
down vote
favorite
I did an exercise of a train travel planner. But it seems like a lot of code to do a simple thing? Is there a better way of writing the JavaScript?
Overview:
The planner needs to be able to find connecting station between origin and destination, then print out the traveling line. Also state how many stops there are.
Please see this JS fiddle containing my code for this exercise.
HTML:
<form id="trip-planner-form">
<label for="origin">Origin</label>
<select name="origin" id="origin"></select>
<label for="destination">Destination</label>
<select name="destination" id="destination"></select>
<button type="submit">Check</button>
</form>
<div id="planner-result"></div>
JS Code:
const data = [
id: 'alamein',
label: 'Alamein',
stops: [
'Flinders Street',
'Richmond',
'East Richmond',
'Burnley',
'Hawthorn',
'Glenferrie'
]
,
id: 'glen-waverly',
label: 'Glen Waverly',
stops: [
'Flagstaff',
'Melbourne Central',
'Parliament',
'Richmond',
'Kooyong and Tooronga'
]
,
id: 'sandringham',
label: 'Sandringham',
stops: [
'Southern Cross',
'Richmond',
'South Yarra',
'Prahran',
'Windsor'
]
];
const form_submit = document.getElementById('trip-planner-form');
const planner_result = document.getElementById('planner-result');
const origin_select = document.getElementById('origin');
const destination_select = document.getElementById('destination');
DOMReady();
function DOMReady()
console.log('dom ready');
loadStops(getStops(data));
set_planner_form_events();
function getStops(lines)
return lines.reduce((accum, current) =>
return accum.concat(current.stops);
, )
// remove duplicate
.filter((f, index, arr) =>
return arr.indexOf(f) === index;
).sort();
function loadStops(stops)
stops.forEach(stop =>
var stop_option = document.createElement('option');
stop_option.value = stop;
stop_option.textContent = stop;
// Append
origin_select.appendChild(stop_option);
destination_select.appendChild(stop_option.cloneNode(true));
);
function set_planner_form_events()
form_submit.addEventListener('submit', event =>
event.preventDefault();
print_planner_result();
);
function print_planner_result()
var origin = origin_select.value;
var destination = destination_select.value;
var result = '';
if (origin === destination)
result = 'You selected the same station.';
else
let traveling_stops = get_traveling_stops(origin, destination);
console.log(traveling_stops);
if (traveling_stops)
result = `<p>$traveling_stops.concat().join(' --> ')</p>`;
result += `<p>total: $traveling_stops.length stops </p>`;
else
result = 'Something went wrong.'
planner_result.innerHTML = result;
function get_traveling_stops(origin, destination)
// Find origin and destination index
var origin_line_index = data.findIndex(d => d.stops.indexOf(origin) > -1);
var dest_Line_index = data.findIndex(d => d.stops.indexOf(destination) > -1);
if (origin_line_index === -1
function get_connecting_station(line1, line2)
for (var i = 0; i < line1.stops.length; i++)
let stop_index = line2.stops.indexOf(line1.stops[i]);
if (stop_index > -1)
return line1.stops[i];
return false;
javascript array
add a comment |Â
up vote
2
down vote
favorite
I did an exercise of a train travel planner. But it seems like a lot of code to do a simple thing? Is there a better way of writing the JavaScript?
Overview:
The planner needs to be able to find connecting station between origin and destination, then print out the traveling line. Also state how many stops there are.
Please see this JS fiddle containing my code for this exercise.
HTML:
<form id="trip-planner-form">
<label for="origin">Origin</label>
<select name="origin" id="origin"></select>
<label for="destination">Destination</label>
<select name="destination" id="destination"></select>
<button type="submit">Check</button>
</form>
<div id="planner-result"></div>
JS Code:
const data = [
id: 'alamein',
label: 'Alamein',
stops: [
'Flinders Street',
'Richmond',
'East Richmond',
'Burnley',
'Hawthorn',
'Glenferrie'
]
,
id: 'glen-waverly',
label: 'Glen Waverly',
stops: [
'Flagstaff',
'Melbourne Central',
'Parliament',
'Richmond',
'Kooyong and Tooronga'
]
,
id: 'sandringham',
label: 'Sandringham',
stops: [
'Southern Cross',
'Richmond',
'South Yarra',
'Prahran',
'Windsor'
]
];
const form_submit = document.getElementById('trip-planner-form');
const planner_result = document.getElementById('planner-result');
const origin_select = document.getElementById('origin');
const destination_select = document.getElementById('destination');
DOMReady();
function DOMReady()
console.log('dom ready');
loadStops(getStops(data));
set_planner_form_events();
function getStops(lines)
return lines.reduce((accum, current) =>
return accum.concat(current.stops);
, )
// remove duplicate
.filter((f, index, arr) =>
return arr.indexOf(f) === index;
).sort();
function loadStops(stops)
stops.forEach(stop =>
var stop_option = document.createElement('option');
stop_option.value = stop;
stop_option.textContent = stop;
// Append
origin_select.appendChild(stop_option);
destination_select.appendChild(stop_option.cloneNode(true));
);
function set_planner_form_events()
form_submit.addEventListener('submit', event =>
event.preventDefault();
print_planner_result();
);
function print_planner_result()
var origin = origin_select.value;
var destination = destination_select.value;
var result = '';
if (origin === destination)
result = 'You selected the same station.';
else
let traveling_stops = get_traveling_stops(origin, destination);
console.log(traveling_stops);
if (traveling_stops)
result = `<p>$traveling_stops.concat().join(' --> ')</p>`;
result += `<p>total: $traveling_stops.length stops </p>`;
else
result = 'Something went wrong.'
planner_result.innerHTML = result;
function get_traveling_stops(origin, destination)
// Find origin and destination index
var origin_line_index = data.findIndex(d => d.stops.indexOf(origin) > -1);
var dest_Line_index = data.findIndex(d => d.stops.indexOf(destination) > -1);
if (origin_line_index === -1
function get_connecting_station(line1, line2)
for (var i = 0; i < line1.stops.length; i++)
let stop_index = line2.stops.indexOf(line1.stops[i]);
if (stop_index > -1)
return line1.stops[i];
return false;
javascript array
I don't think your planner works as intended. Given lines A-B, B-C, C-D, D-E, the plan for traveling from A to E is "A --> D --> E"?
â le_m
Jan 4 at 14:28
Did you assume that all destinations are at maximum one change of line away from any origin? Also, could it be that for Burnley -> Windsor, the stops Prahran and South Yarra are switched in the resulting travel plan?
â le_m
Jan 4 at 14:36
Welcome to Code Review! I changed the title so that it describes what the code does per site goals: "State what your code does in your title, not your main concerns about it.". Feel free to give it a different title if there is something more appropriate.
â Sam Onela
Jan 4 at 17:02
add a comment |Â
up vote
2
down vote
favorite
up vote
2
down vote
favorite
I did an exercise of a train travel planner. But it seems like a lot of code to do a simple thing? Is there a better way of writing the JavaScript?
Overview:
The planner needs to be able to find connecting station between origin and destination, then print out the traveling line. Also state how many stops there are.
Please see this JS fiddle containing my code for this exercise.
HTML:
<form id="trip-planner-form">
<label for="origin">Origin</label>
<select name="origin" id="origin"></select>
<label for="destination">Destination</label>
<select name="destination" id="destination"></select>
<button type="submit">Check</button>
</form>
<div id="planner-result"></div>
JS Code:
const data = [
id: 'alamein',
label: 'Alamein',
stops: [
'Flinders Street',
'Richmond',
'East Richmond',
'Burnley',
'Hawthorn',
'Glenferrie'
]
,
id: 'glen-waverly',
label: 'Glen Waverly',
stops: [
'Flagstaff',
'Melbourne Central',
'Parliament',
'Richmond',
'Kooyong and Tooronga'
]
,
id: 'sandringham',
label: 'Sandringham',
stops: [
'Southern Cross',
'Richmond',
'South Yarra',
'Prahran',
'Windsor'
]
];
const form_submit = document.getElementById('trip-planner-form');
const planner_result = document.getElementById('planner-result');
const origin_select = document.getElementById('origin');
const destination_select = document.getElementById('destination');
DOMReady();
function DOMReady()
console.log('dom ready');
loadStops(getStops(data));
set_planner_form_events();
function getStops(lines)
return lines.reduce((accum, current) =>
return accum.concat(current.stops);
, )
// remove duplicate
.filter((f, index, arr) =>
return arr.indexOf(f) === index;
).sort();
function loadStops(stops)
stops.forEach(stop =>
var stop_option = document.createElement('option');
stop_option.value = stop;
stop_option.textContent = stop;
// Append
origin_select.appendChild(stop_option);
destination_select.appendChild(stop_option.cloneNode(true));
);
function set_planner_form_events()
form_submit.addEventListener('submit', event =>
event.preventDefault();
print_planner_result();
);
function print_planner_result()
var origin = origin_select.value;
var destination = destination_select.value;
var result = '';
if (origin === destination)
result = 'You selected the same station.';
else
let traveling_stops = get_traveling_stops(origin, destination);
console.log(traveling_stops);
if (traveling_stops)
result = `<p>$traveling_stops.concat().join(' --> ')</p>`;
result += `<p>total: $traveling_stops.length stops </p>`;
else
result = 'Something went wrong.'
planner_result.innerHTML = result;
function get_traveling_stops(origin, destination)
// Find origin and destination index
var origin_line_index = data.findIndex(d => d.stops.indexOf(origin) > -1);
var dest_Line_index = data.findIndex(d => d.stops.indexOf(destination) > -1);
if (origin_line_index === -1
function get_connecting_station(line1, line2)
for (var i = 0; i < line1.stops.length; i++)
let stop_index = line2.stops.indexOf(line1.stops[i]);
if (stop_index > -1)
return line1.stops[i];
return false;
javascript array
I did an exercise of a train travel planner. But it seems like a lot of code to do a simple thing? Is there a better way of writing the JavaScript?
Overview:
The planner needs to be able to find connecting station between origin and destination, then print out the traveling line. Also state how many stops there are.
Please see this JS fiddle containing my code for this exercise.
HTML:
<form id="trip-planner-form">
<label for="origin">Origin</label>
<select name="origin" id="origin"></select>
<label for="destination">Destination</label>
<select name="destination" id="destination"></select>
<button type="submit">Check</button>
</form>
<div id="planner-result"></div>
JS Code:
const data = [
id: 'alamein',
label: 'Alamein',
stops: [
'Flinders Street',
'Richmond',
'East Richmond',
'Burnley',
'Hawthorn',
'Glenferrie'
]
,
id: 'glen-waverly',
label: 'Glen Waverly',
stops: [
'Flagstaff',
'Melbourne Central',
'Parliament',
'Richmond',
'Kooyong and Tooronga'
]
,
id: 'sandringham',
label: 'Sandringham',
stops: [
'Southern Cross',
'Richmond',
'South Yarra',
'Prahran',
'Windsor'
]
];
const form_submit = document.getElementById('trip-planner-form');
const planner_result = document.getElementById('planner-result');
const origin_select = document.getElementById('origin');
const destination_select = document.getElementById('destination');
DOMReady();
function DOMReady()
console.log('dom ready');
loadStops(getStops(data));
set_planner_form_events();
function getStops(lines)
return lines.reduce((accum, current) =>
return accum.concat(current.stops);
, )
// remove duplicate
.filter((f, index, arr) =>
return arr.indexOf(f) === index;
).sort();
function loadStops(stops)
stops.forEach(stop =>
var stop_option = document.createElement('option');
stop_option.value = stop;
stop_option.textContent = stop;
// Append
origin_select.appendChild(stop_option);
destination_select.appendChild(stop_option.cloneNode(true));
);
function set_planner_form_events()
form_submit.addEventListener('submit', event =>
event.preventDefault();
print_planner_result();
);
function print_planner_result()
var origin = origin_select.value;
var destination = destination_select.value;
var result = '';
if (origin === destination)
result = 'You selected the same station.';
else
let traveling_stops = get_traveling_stops(origin, destination);
console.log(traveling_stops);
if (traveling_stops)
result = `<p>$traveling_stops.concat().join(' --> ')</p>`;
result += `<p>total: $traveling_stops.length stops </p>`;
else
result = 'Something went wrong.'
planner_result.innerHTML = result;
function get_traveling_stops(origin, destination)
// Find origin and destination index
var origin_line_index = data.findIndex(d => d.stops.indexOf(origin) > -1);
var dest_Line_index = data.findIndex(d => d.stops.indexOf(destination) > -1);
if (origin_line_index === -1
function get_connecting_station(line1, line2)
for (var i = 0; i < line1.stops.length; i++)
let stop_index = line2.stops.indexOf(line1.stops[i]);
if (stop_index > -1)
return line1.stops[i];
return false;
javascript array
edited Jan 4 at 17:01
Sam Onela
5,88461545
5,88461545
asked Jan 4 at 13:41
Ray Tsai
132
132
I don't think your planner works as intended. Given lines A-B, B-C, C-D, D-E, the plan for traveling from A to E is "A --> D --> E"?
â le_m
Jan 4 at 14:28
Did you assume that all destinations are at maximum one change of line away from any origin? Also, could it be that for Burnley -> Windsor, the stops Prahran and South Yarra are switched in the resulting travel plan?
â le_m
Jan 4 at 14:36
Welcome to Code Review! I changed the title so that it describes what the code does per site goals: "State what your code does in your title, not your main concerns about it.". Feel free to give it a different title if there is something more appropriate.
â Sam Onela
Jan 4 at 17:02
add a comment |Â
I don't think your planner works as intended. Given lines A-B, B-C, C-D, D-E, the plan for traveling from A to E is "A --> D --> E"?
â le_m
Jan 4 at 14:28
Did you assume that all destinations are at maximum one change of line away from any origin? Also, could it be that for Burnley -> Windsor, the stops Prahran and South Yarra are switched in the resulting travel plan?
â le_m
Jan 4 at 14:36
Welcome to Code Review! I changed the title so that it describes what the code does per site goals: "State what your code does in your title, not your main concerns about it.". Feel free to give it a different title if there is something more appropriate.
â Sam Onela
Jan 4 at 17:02
I don't think your planner works as intended. Given lines A-B, B-C, C-D, D-E, the plan for traveling from A to E is "A --> D --> E"?
â le_m
Jan 4 at 14:28
I don't think your planner works as intended. Given lines A-B, B-C, C-D, D-E, the plan for traveling from A to E is "A --> D --> E"?
â le_m
Jan 4 at 14:28
Did you assume that all destinations are at maximum one change of line away from any origin? Also, could it be that for Burnley -> Windsor, the stops Prahran and South Yarra are switched in the resulting travel plan?
â le_m
Jan 4 at 14:36
Did you assume that all destinations are at maximum one change of line away from any origin? Also, could it be that for Burnley -> Windsor, the stops Prahran and South Yarra are switched in the resulting travel plan?
â le_m
Jan 4 at 14:36
Welcome to Code Review! I changed the title so that it describes what the code does per site goals: "State what your code does in your title, not your main concerns about it.". Feel free to give it a different title if there is something more appropriate.
â Sam Onela
Jan 4 at 17:02
Welcome to Code Review! I changed the title so that it describes what the code does per site goals: "State what your code does in your title, not your main concerns about it.". Feel free to give it a different title if there is something more appropriate.
â Sam Onela
Jan 4 at 17:02
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
-2
down vote
accepted
Simple solution
The problem is trivial as there is only one hub station. This means that there is only one root between any two stations.
You need only find which line each station is on. If not the same line then find the root on starting line to the hub and from the destination station hub to the destination station.
If the problem involved a configuration that allowed more than one root between stations it becomes much more involved but your code does not show that is an issue.
Simplify using functions.
The reason why your code seams long is because you have not compartmentalised functionality in the form of functions.
You can break it down to
- Finding a line for a station
- Getting stops between stations on a line
- Finding a root between stations
- Displaying a root.
By breaking the problem into smaller parts you reduce the overall complexity and make it easier to read and maintain.
function findLineForStation(station)
return data.find(line => line.stops.includes(station));
function getStops(line, fromStation ,toStation, skipFirst = false)
const idxFrom = line.stops.indexOf(fromStation);
const idxTo = line.stops.indexOf(toStation);
const count = Math.abs(idxTo - idxFrom);
const dir = Math.sign(idxTo - idxFrom);
const stops = ;
var i;
for (i = skipFirst ? 1 : 0; i <= count; i ++)
stops.push(line.stops[idxFrom + i * dir]);
return stops;
function findRoot(fromStation, toStation)
const hubStation = "Richmond";
const fromLine = findLineForStation(fromStation);
const toLine = findLineForStation(toStation);
if (fromStation === hubStation) fromLine = toLine
if (fromLine === toLine)
return getStops(fromLine, fromStation, toStation);
return [
...getStops(fromLine, fromStation, hubStation),
...getStops(toLine, hubStation, toStation, true)
];
function displayRoot()
root.textContent = findRoot(originElId.value, destinationElId.value).join(" => ");
originElId.addEventListener("change",displayRoot);
destinationElId.addEventListener("change",displayRoot);
const data = [
id: 'alamein',
label: 'Alamein',
stops: ['Flinders Street', 'Richmond', 'East Richmond', 'Burnley', 'Hawthorn', 'Glenferrie']
,
id: 'glen-waverly',
label: 'Glen Waverly',
stops: ['Flagstaff', 'Melbourne Central', 'Parliament', 'Richmond', 'Kooyong and Tooronga']
,
id: 'sandringham',
label: 'Sandringham',
stops: ['Southern Cross', 'Richmond', 'South Yarra', 'Prahran', 'Windsor']
];
From <select name="origin" id="originElId"><option value="Burnley">Burnley</option><option value="East Richmond">East Richmond</option><option value="Flagstaff">Flagstaff</option><option value="Flinders Street">Flinders Street</option><option value="Glenferrie">Glenferrie</option><option value="Hawthorn">Hawthorn</option><option value="Kooyong and Tooronga">Kooyong and Tooronga</option><option value="Melbourne Central">Melbourne Central</option><option value="Parliament">Parliament</option><option value="Prahran">Prahran</option><option value="Richmond">Richmond</option><option value="South Yarra">South Yarra</option><option value="Southern Cross">Southern Cross</option><option value="Windsor">Windsor</option></select><br>
Destination <select name="destination" id="destinationElId"><option value="Burnley">Burnley</option><option value="East Richmond">East Richmond</option><option value="Flagstaff">Flagstaff</option><option value="Flinders Street">Flinders Street</option><option value="Glenferrie">Glenferrie</option><option value="Hawthorn">Hawthorn</option><option value="Kooyong and Tooronga">Kooyong and Tooronga</option><option value="Melbourne Central">Melbourne Central</option><option value="Parliament">Parliament</option><option value="Prahran">Prahran</option><option value="Richmond">Richmond</option><option value="South Yarra">South Yarra</option><option value="Southern Cross">Southern Cross</option><option value="Windsor">Windsor</option></select>
<div id="root"></div>
thanks a lot! This is pretty awesome. IDK why it was downvoted. I liked the use of Math.sign to solve the directional problem and use of Array.find() and Array.include() ... I should've used those! Im just gonna leave open for a bit to see if there are more different solutions :)
â Ray Tsai
Jan 4 at 22:41
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
-2
down vote
accepted
Simple solution
The problem is trivial as there is only one hub station. This means that there is only one root between any two stations.
You need only find which line each station is on. If not the same line then find the root on starting line to the hub and from the destination station hub to the destination station.
If the problem involved a configuration that allowed more than one root between stations it becomes much more involved but your code does not show that is an issue.
Simplify using functions.
The reason why your code seams long is because you have not compartmentalised functionality in the form of functions.
You can break it down to
- Finding a line for a station
- Getting stops between stations on a line
- Finding a root between stations
- Displaying a root.
By breaking the problem into smaller parts you reduce the overall complexity and make it easier to read and maintain.
function findLineForStation(station)
return data.find(line => line.stops.includes(station));
function getStops(line, fromStation ,toStation, skipFirst = false)
const idxFrom = line.stops.indexOf(fromStation);
const idxTo = line.stops.indexOf(toStation);
const count = Math.abs(idxTo - idxFrom);
const dir = Math.sign(idxTo - idxFrom);
const stops = ;
var i;
for (i = skipFirst ? 1 : 0; i <= count; i ++)
stops.push(line.stops[idxFrom + i * dir]);
return stops;
function findRoot(fromStation, toStation)
const hubStation = "Richmond";
const fromLine = findLineForStation(fromStation);
const toLine = findLineForStation(toStation);
if (fromStation === hubStation) fromLine = toLine
if (fromLine === toLine)
return getStops(fromLine, fromStation, toStation);
return [
...getStops(fromLine, fromStation, hubStation),
...getStops(toLine, hubStation, toStation, true)
];
function displayRoot()
root.textContent = findRoot(originElId.value, destinationElId.value).join(" => ");
originElId.addEventListener("change",displayRoot);
destinationElId.addEventListener("change",displayRoot);
const data = [
id: 'alamein',
label: 'Alamein',
stops: ['Flinders Street', 'Richmond', 'East Richmond', 'Burnley', 'Hawthorn', 'Glenferrie']
,
id: 'glen-waverly',
label: 'Glen Waverly',
stops: ['Flagstaff', 'Melbourne Central', 'Parliament', 'Richmond', 'Kooyong and Tooronga']
,
id: 'sandringham',
label: 'Sandringham',
stops: ['Southern Cross', 'Richmond', 'South Yarra', 'Prahran', 'Windsor']
];
From <select name="origin" id="originElId"><option value="Burnley">Burnley</option><option value="East Richmond">East Richmond</option><option value="Flagstaff">Flagstaff</option><option value="Flinders Street">Flinders Street</option><option value="Glenferrie">Glenferrie</option><option value="Hawthorn">Hawthorn</option><option value="Kooyong and Tooronga">Kooyong and Tooronga</option><option value="Melbourne Central">Melbourne Central</option><option value="Parliament">Parliament</option><option value="Prahran">Prahran</option><option value="Richmond">Richmond</option><option value="South Yarra">South Yarra</option><option value="Southern Cross">Southern Cross</option><option value="Windsor">Windsor</option></select><br>
Destination <select name="destination" id="destinationElId"><option value="Burnley">Burnley</option><option value="East Richmond">East Richmond</option><option value="Flagstaff">Flagstaff</option><option value="Flinders Street">Flinders Street</option><option value="Glenferrie">Glenferrie</option><option value="Hawthorn">Hawthorn</option><option value="Kooyong and Tooronga">Kooyong and Tooronga</option><option value="Melbourne Central">Melbourne Central</option><option value="Parliament">Parliament</option><option value="Prahran">Prahran</option><option value="Richmond">Richmond</option><option value="South Yarra">South Yarra</option><option value="Southern Cross">Southern Cross</option><option value="Windsor">Windsor</option></select>
<div id="root"></div>
thanks a lot! This is pretty awesome. IDK why it was downvoted. I liked the use of Math.sign to solve the directional problem and use of Array.find() and Array.include() ... I should've used those! Im just gonna leave open for a bit to see if there are more different solutions :)
â Ray Tsai
Jan 4 at 22:41
add a comment |Â
up vote
-2
down vote
accepted
Simple solution
The problem is trivial as there is only one hub station. This means that there is only one root between any two stations.
You need only find which line each station is on. If not the same line then find the root on starting line to the hub and from the destination station hub to the destination station.
If the problem involved a configuration that allowed more than one root between stations it becomes much more involved but your code does not show that is an issue.
Simplify using functions.
The reason why your code seams long is because you have not compartmentalised functionality in the form of functions.
You can break it down to
- Finding a line for a station
- Getting stops between stations on a line
- Finding a root between stations
- Displaying a root.
By breaking the problem into smaller parts you reduce the overall complexity and make it easier to read and maintain.
function findLineForStation(station)
return data.find(line => line.stops.includes(station));
function getStops(line, fromStation ,toStation, skipFirst = false)
const idxFrom = line.stops.indexOf(fromStation);
const idxTo = line.stops.indexOf(toStation);
const count = Math.abs(idxTo - idxFrom);
const dir = Math.sign(idxTo - idxFrom);
const stops = ;
var i;
for (i = skipFirst ? 1 : 0; i <= count; i ++)
stops.push(line.stops[idxFrom + i * dir]);
return stops;
function findRoot(fromStation, toStation)
const hubStation = "Richmond";
const fromLine = findLineForStation(fromStation);
const toLine = findLineForStation(toStation);
if (fromStation === hubStation) fromLine = toLine
if (fromLine === toLine)
return getStops(fromLine, fromStation, toStation);
return [
...getStops(fromLine, fromStation, hubStation),
...getStops(toLine, hubStation, toStation, true)
];
function displayRoot()
root.textContent = findRoot(originElId.value, destinationElId.value).join(" => ");
originElId.addEventListener("change",displayRoot);
destinationElId.addEventListener("change",displayRoot);
const data = [
id: 'alamein',
label: 'Alamein',
stops: ['Flinders Street', 'Richmond', 'East Richmond', 'Burnley', 'Hawthorn', 'Glenferrie']
,
id: 'glen-waverly',
label: 'Glen Waverly',
stops: ['Flagstaff', 'Melbourne Central', 'Parliament', 'Richmond', 'Kooyong and Tooronga']
,
id: 'sandringham',
label: 'Sandringham',
stops: ['Southern Cross', 'Richmond', 'South Yarra', 'Prahran', 'Windsor']
];
From <select name="origin" id="originElId"><option value="Burnley">Burnley</option><option value="East Richmond">East Richmond</option><option value="Flagstaff">Flagstaff</option><option value="Flinders Street">Flinders Street</option><option value="Glenferrie">Glenferrie</option><option value="Hawthorn">Hawthorn</option><option value="Kooyong and Tooronga">Kooyong and Tooronga</option><option value="Melbourne Central">Melbourne Central</option><option value="Parliament">Parliament</option><option value="Prahran">Prahran</option><option value="Richmond">Richmond</option><option value="South Yarra">South Yarra</option><option value="Southern Cross">Southern Cross</option><option value="Windsor">Windsor</option></select><br>
Destination <select name="destination" id="destinationElId"><option value="Burnley">Burnley</option><option value="East Richmond">East Richmond</option><option value="Flagstaff">Flagstaff</option><option value="Flinders Street">Flinders Street</option><option value="Glenferrie">Glenferrie</option><option value="Hawthorn">Hawthorn</option><option value="Kooyong and Tooronga">Kooyong and Tooronga</option><option value="Melbourne Central">Melbourne Central</option><option value="Parliament">Parliament</option><option value="Prahran">Prahran</option><option value="Richmond">Richmond</option><option value="South Yarra">South Yarra</option><option value="Southern Cross">Southern Cross</option><option value="Windsor">Windsor</option></select>
<div id="root"></div>
thanks a lot! This is pretty awesome. IDK why it was downvoted. I liked the use of Math.sign to solve the directional problem and use of Array.find() and Array.include() ... I should've used those! Im just gonna leave open for a bit to see if there are more different solutions :)
â Ray Tsai
Jan 4 at 22:41
add a comment |Â
up vote
-2
down vote
accepted
up vote
-2
down vote
accepted
Simple solution
The problem is trivial as there is only one hub station. This means that there is only one root between any two stations.
You need only find which line each station is on. If not the same line then find the root on starting line to the hub and from the destination station hub to the destination station.
If the problem involved a configuration that allowed more than one root between stations it becomes much more involved but your code does not show that is an issue.
Simplify using functions.
The reason why your code seams long is because you have not compartmentalised functionality in the form of functions.
You can break it down to
- Finding a line for a station
- Getting stops between stations on a line
- Finding a root between stations
- Displaying a root.
By breaking the problem into smaller parts you reduce the overall complexity and make it easier to read and maintain.
function findLineForStation(station)
return data.find(line => line.stops.includes(station));
function getStops(line, fromStation ,toStation, skipFirst = false)
const idxFrom = line.stops.indexOf(fromStation);
const idxTo = line.stops.indexOf(toStation);
const count = Math.abs(idxTo - idxFrom);
const dir = Math.sign(idxTo - idxFrom);
const stops = ;
var i;
for (i = skipFirst ? 1 : 0; i <= count; i ++)
stops.push(line.stops[idxFrom + i * dir]);
return stops;
function findRoot(fromStation, toStation)
const hubStation = "Richmond";
const fromLine = findLineForStation(fromStation);
const toLine = findLineForStation(toStation);
if (fromStation === hubStation) fromLine = toLine
if (fromLine === toLine)
return getStops(fromLine, fromStation, toStation);
return [
...getStops(fromLine, fromStation, hubStation),
...getStops(toLine, hubStation, toStation, true)
];
function displayRoot()
root.textContent = findRoot(originElId.value, destinationElId.value).join(" => ");
originElId.addEventListener("change",displayRoot);
destinationElId.addEventListener("change",displayRoot);
const data = [
id: 'alamein',
label: 'Alamein',
stops: ['Flinders Street', 'Richmond', 'East Richmond', 'Burnley', 'Hawthorn', 'Glenferrie']
,
id: 'glen-waverly',
label: 'Glen Waverly',
stops: ['Flagstaff', 'Melbourne Central', 'Parliament', 'Richmond', 'Kooyong and Tooronga']
,
id: 'sandringham',
label: 'Sandringham',
stops: ['Southern Cross', 'Richmond', 'South Yarra', 'Prahran', 'Windsor']
];
From <select name="origin" id="originElId"><option value="Burnley">Burnley</option><option value="East Richmond">East Richmond</option><option value="Flagstaff">Flagstaff</option><option value="Flinders Street">Flinders Street</option><option value="Glenferrie">Glenferrie</option><option value="Hawthorn">Hawthorn</option><option value="Kooyong and Tooronga">Kooyong and Tooronga</option><option value="Melbourne Central">Melbourne Central</option><option value="Parliament">Parliament</option><option value="Prahran">Prahran</option><option value="Richmond">Richmond</option><option value="South Yarra">South Yarra</option><option value="Southern Cross">Southern Cross</option><option value="Windsor">Windsor</option></select><br>
Destination <select name="destination" id="destinationElId"><option value="Burnley">Burnley</option><option value="East Richmond">East Richmond</option><option value="Flagstaff">Flagstaff</option><option value="Flinders Street">Flinders Street</option><option value="Glenferrie">Glenferrie</option><option value="Hawthorn">Hawthorn</option><option value="Kooyong and Tooronga">Kooyong and Tooronga</option><option value="Melbourne Central">Melbourne Central</option><option value="Parliament">Parliament</option><option value="Prahran">Prahran</option><option value="Richmond">Richmond</option><option value="South Yarra">South Yarra</option><option value="Southern Cross">Southern Cross</option><option value="Windsor">Windsor</option></select>
<div id="root"></div>
Simple solution
The problem is trivial as there is only one hub station. This means that there is only one root between any two stations.
You need only find which line each station is on. If not the same line then find the root on starting line to the hub and from the destination station hub to the destination station.
If the problem involved a configuration that allowed more than one root between stations it becomes much more involved but your code does not show that is an issue.
Simplify using functions.
The reason why your code seams long is because you have not compartmentalised functionality in the form of functions.
You can break it down to
- Finding a line for a station
- Getting stops between stations on a line
- Finding a root between stations
- Displaying a root.
By breaking the problem into smaller parts you reduce the overall complexity and make it easier to read and maintain.
function findLineForStation(station)
return data.find(line => line.stops.includes(station));
function getStops(line, fromStation ,toStation, skipFirst = false)
const idxFrom = line.stops.indexOf(fromStation);
const idxTo = line.stops.indexOf(toStation);
const count = Math.abs(idxTo - idxFrom);
const dir = Math.sign(idxTo - idxFrom);
const stops = ;
var i;
for (i = skipFirst ? 1 : 0; i <= count; i ++)
stops.push(line.stops[idxFrom + i * dir]);
return stops;
function findRoot(fromStation, toStation)
const hubStation = "Richmond";
const fromLine = findLineForStation(fromStation);
const toLine = findLineForStation(toStation);
if (fromStation === hubStation) fromLine = toLine
if (fromLine === toLine)
return getStops(fromLine, fromStation, toStation);
return [
...getStops(fromLine, fromStation, hubStation),
...getStops(toLine, hubStation, toStation, true)
];
function displayRoot()
root.textContent = findRoot(originElId.value, destinationElId.value).join(" => ");
originElId.addEventListener("change",displayRoot);
destinationElId.addEventListener("change",displayRoot);
const data = [
id: 'alamein',
label: 'Alamein',
stops: ['Flinders Street', 'Richmond', 'East Richmond', 'Burnley', 'Hawthorn', 'Glenferrie']
,
id: 'glen-waverly',
label: 'Glen Waverly',
stops: ['Flagstaff', 'Melbourne Central', 'Parliament', 'Richmond', 'Kooyong and Tooronga']
,
id: 'sandringham',
label: 'Sandringham',
stops: ['Southern Cross', 'Richmond', 'South Yarra', 'Prahran', 'Windsor']
];
From <select name="origin" id="originElId"><option value="Burnley">Burnley</option><option value="East Richmond">East Richmond</option><option value="Flagstaff">Flagstaff</option><option value="Flinders Street">Flinders Street</option><option value="Glenferrie">Glenferrie</option><option value="Hawthorn">Hawthorn</option><option value="Kooyong and Tooronga">Kooyong and Tooronga</option><option value="Melbourne Central">Melbourne Central</option><option value="Parliament">Parliament</option><option value="Prahran">Prahran</option><option value="Richmond">Richmond</option><option value="South Yarra">South Yarra</option><option value="Southern Cross">Southern Cross</option><option value="Windsor">Windsor</option></select><br>
Destination <select name="destination" id="destinationElId"><option value="Burnley">Burnley</option><option value="East Richmond">East Richmond</option><option value="Flagstaff">Flagstaff</option><option value="Flinders Street">Flinders Street</option><option value="Glenferrie">Glenferrie</option><option value="Hawthorn">Hawthorn</option><option value="Kooyong and Tooronga">Kooyong and Tooronga</option><option value="Melbourne Central">Melbourne Central</option><option value="Parliament">Parliament</option><option value="Prahran">Prahran</option><option value="Richmond">Richmond</option><option value="South Yarra">South Yarra</option><option value="Southern Cross">Southern Cross</option><option value="Windsor">Windsor</option></select>
<div id="root"></div>
function findLineForStation(station)
return data.find(line => line.stops.includes(station));
function getStops(line, fromStation ,toStation, skipFirst = false)
const idxFrom = line.stops.indexOf(fromStation);
const idxTo = line.stops.indexOf(toStation);
const count = Math.abs(idxTo - idxFrom);
const dir = Math.sign(idxTo - idxFrom);
const stops = ;
var i;
for (i = skipFirst ? 1 : 0; i <= count; i ++)
stops.push(line.stops[idxFrom + i * dir]);
return stops;
function findRoot(fromStation, toStation)
const hubStation = "Richmond";
const fromLine = findLineForStation(fromStation);
const toLine = findLineForStation(toStation);
if (fromStation === hubStation) fromLine = toLine
if (fromLine === toLine)
return getStops(fromLine, fromStation, toStation);
return [
...getStops(fromLine, fromStation, hubStation),
...getStops(toLine, hubStation, toStation, true)
];
function displayRoot()
root.textContent = findRoot(originElId.value, destinationElId.value).join(" => ");
originElId.addEventListener("change",displayRoot);
destinationElId.addEventListener("change",displayRoot);
const data = [
id: 'alamein',
label: 'Alamein',
stops: ['Flinders Street', 'Richmond', 'East Richmond', 'Burnley', 'Hawthorn', 'Glenferrie']
,
id: 'glen-waverly',
label: 'Glen Waverly',
stops: ['Flagstaff', 'Melbourne Central', 'Parliament', 'Richmond', 'Kooyong and Tooronga']
,
id: 'sandringham',
label: 'Sandringham',
stops: ['Southern Cross', 'Richmond', 'South Yarra', 'Prahran', 'Windsor']
];
From <select name="origin" id="originElId"><option value="Burnley">Burnley</option><option value="East Richmond">East Richmond</option><option value="Flagstaff">Flagstaff</option><option value="Flinders Street">Flinders Street</option><option value="Glenferrie">Glenferrie</option><option value="Hawthorn">Hawthorn</option><option value="Kooyong and Tooronga">Kooyong and Tooronga</option><option value="Melbourne Central">Melbourne Central</option><option value="Parliament">Parliament</option><option value="Prahran">Prahran</option><option value="Richmond">Richmond</option><option value="South Yarra">South Yarra</option><option value="Southern Cross">Southern Cross</option><option value="Windsor">Windsor</option></select><br>
Destination <select name="destination" id="destinationElId"><option value="Burnley">Burnley</option><option value="East Richmond">East Richmond</option><option value="Flagstaff">Flagstaff</option><option value="Flinders Street">Flinders Street</option><option value="Glenferrie">Glenferrie</option><option value="Hawthorn">Hawthorn</option><option value="Kooyong and Tooronga">Kooyong and Tooronga</option><option value="Melbourne Central">Melbourne Central</option><option value="Parliament">Parliament</option><option value="Prahran">Prahran</option><option value="Richmond">Richmond</option><option value="South Yarra">South Yarra</option><option value="Southern Cross">Southern Cross</option><option value="Windsor">Windsor</option></select>
<div id="root"></div>
function findLineForStation(station)
return data.find(line => line.stops.includes(station));
function getStops(line, fromStation ,toStation, skipFirst = false)
const idxFrom = line.stops.indexOf(fromStation);
const idxTo = line.stops.indexOf(toStation);
const count = Math.abs(idxTo - idxFrom);
const dir = Math.sign(idxTo - idxFrom);
const stops = ;
var i;
for (i = skipFirst ? 1 : 0; i <= count; i ++)
stops.push(line.stops[idxFrom + i * dir]);
return stops;
function findRoot(fromStation, toStation)
const hubStation = "Richmond";
const fromLine = findLineForStation(fromStation);
const toLine = findLineForStation(toStation);
if (fromStation === hubStation) fromLine = toLine
if (fromLine === toLine)
return getStops(fromLine, fromStation, toStation);
return [
...getStops(fromLine, fromStation, hubStation),
...getStops(toLine, hubStation, toStation, true)
];
function displayRoot()
root.textContent = findRoot(originElId.value, destinationElId.value).join(" => ");
originElId.addEventListener("change",displayRoot);
destinationElId.addEventListener("change",displayRoot);
const data = [
id: 'alamein',
label: 'Alamein',
stops: ['Flinders Street', 'Richmond', 'East Richmond', 'Burnley', 'Hawthorn', 'Glenferrie']
,
id: 'glen-waverly',
label: 'Glen Waverly',
stops: ['Flagstaff', 'Melbourne Central', 'Parliament', 'Richmond', 'Kooyong and Tooronga']
,
id: 'sandringham',
label: 'Sandringham',
stops: ['Southern Cross', 'Richmond', 'South Yarra', 'Prahran', 'Windsor']
];
From <select name="origin" id="originElId"><option value="Burnley">Burnley</option><option value="East Richmond">East Richmond</option><option value="Flagstaff">Flagstaff</option><option value="Flinders Street">Flinders Street</option><option value="Glenferrie">Glenferrie</option><option value="Hawthorn">Hawthorn</option><option value="Kooyong and Tooronga">Kooyong and Tooronga</option><option value="Melbourne Central">Melbourne Central</option><option value="Parliament">Parliament</option><option value="Prahran">Prahran</option><option value="Richmond">Richmond</option><option value="South Yarra">South Yarra</option><option value="Southern Cross">Southern Cross</option><option value="Windsor">Windsor</option></select><br>
Destination <select name="destination" id="destinationElId"><option value="Burnley">Burnley</option><option value="East Richmond">East Richmond</option><option value="Flagstaff">Flagstaff</option><option value="Flinders Street">Flinders Street</option><option value="Glenferrie">Glenferrie</option><option value="Hawthorn">Hawthorn</option><option value="Kooyong and Tooronga">Kooyong and Tooronga</option><option value="Melbourne Central">Melbourne Central</option><option value="Parliament">Parliament</option><option value="Prahran">Prahran</option><option value="Richmond">Richmond</option><option value="South Yarra">South Yarra</option><option value="Southern Cross">Southern Cross</option><option value="Windsor">Windsor</option></select>
<div id="root"></div>
edited Jan 4 at 17:21
answered Jan 4 at 16:42
Blindman67
5,4251320
5,4251320
thanks a lot! This is pretty awesome. IDK why it was downvoted. I liked the use of Math.sign to solve the directional problem and use of Array.find() and Array.include() ... I should've used those! Im just gonna leave open for a bit to see if there are more different solutions :)
â Ray Tsai
Jan 4 at 22:41
add a comment |Â
thanks a lot! This is pretty awesome. IDK why it was downvoted. I liked the use of Math.sign to solve the directional problem and use of Array.find() and Array.include() ... I should've used those! Im just gonna leave open for a bit to see if there are more different solutions :)
â Ray Tsai
Jan 4 at 22:41
thanks a lot! This is pretty awesome. IDK why it was downvoted. I liked the use of Math.sign to solve the directional problem and use of Array.find() and Array.include() ... I should've used those! Im just gonna leave open for a bit to see if there are more different solutions :)
â Ray Tsai
Jan 4 at 22:41
thanks a lot! This is pretty awesome. IDK why it was downvoted. I liked the use of Math.sign to solve the directional problem and use of Array.find() and Array.include() ... I should've used those! Im just gonna leave open for a bit to see if there are more different solutions :)
â Ray Tsai
Jan 4 at 22:41
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f184281%2ftrain-travel-planner%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
I don't think your planner works as intended. Given lines A-B, B-C, C-D, D-E, the plan for traveling from A to E is "A --> D --> E"?
â le_m
Jan 4 at 14:28
Did you assume that all destinations are at maximum one change of line away from any origin? Also, could it be that for Burnley -> Windsor, the stops Prahran and South Yarra are switched in the resulting travel plan?
â le_m
Jan 4 at 14:36
Welcome to Code Review! I changed the title so that it describes what the code does per site goals: "State what your code does in your title, not your main concerns about it.". Feel free to give it a different title if there is something more appropriate.
â Sam Onela
Jan 4 at 17:02