-
Notifications
You must be signed in to change notification settings - Fork 0
/
problem_02.cpp
112 lines (83 loc) · 2.25 KB
/
problem_02.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include "AoC/2017/problem_02.h"
#include "AoC/problems_map.h"
#include "AoC/utils/parse.h"
#include "range/v3/algorithm/find_if.hpp"
#include "range/v3/algorithm/minmax.hpp"
#include "range/v3/numeric/accumulate.hpp"
#include "range/v3/range/conversion.hpp"
#include "range/v3/view/cartesian_product.hpp"
#include "range/v3/view/common.hpp"
#include "range/v3/view/getlines.hpp"
#include "range/v3/view/transform.hpp"
#include "boost/hof/lift.hpp"
#include <istream>
#include <stdexcept>
#include <string>
#include <vector>
namespace
{
using Num = int;
using Nums = std::vector<Num>;
template <typename Pair>
bool is_divisible( const Pair p )
{
const auto [ x, y ] = p;
return x != y && x % y == 0;
}
Nums parse_row( const std::string& line )
{
namespace x3 = boost::spirit::x3;
const auto parser = *x3::int_;
Nums nums;
const bool is_parsed = AoC::x3_parse( line, parser, x3::space, nums );
if ( !is_parsed )
{
throw std::invalid_argument( "Failed to parse input nums data" );
}
return nums;
}
Num get_minmax_diff( const Nums& nums )
{
const auto mm = ranges::minmax( nums );
return mm.max - mm.min;
}
Num get_evenly_div( const Nums& nums )
{
const auto pairs = ranges::views::cartesian_product( nums, nums );
const auto pairs_iter = ranges::find_if( pairs, BOOST_HOF_LIFT( is_divisible ) );
assert( pairs_iter != pairs.end() );
const auto [ x, y ] = *pairs_iter;
return x / y;
}
template <Num ( *calc_row )( const Nums& )>
int solve( std::istream& input )
{
auto row_diffs = ranges::getlines( input ) | ranges::views::transform( &parse_row ) | ranges::views::transform( calc_row );
return ranges::accumulate( row_diffs, 0 );
}
} // namespace
namespace AoC_2017
{
namespace problem_02
{
int solve_1( std::istream& input )
{
return solve<&get_minmax_diff>( input );
}
int solve_2( std::istream& input )
{
return solve<&get_evenly_div>( input );
}
AOC_REGISTER_PROBLEM( 2017_02, solve_1, solve_2 );
} // namespace problem_02
} // namespace AoC_2017
#ifndef NDEBUG
# include "impl_tests.h"
# include <cassert>
static void impl_tests()
{
assert( ( std::vector<Num>{ 5, 1, 9, 5 } ) == parse_row( "5 1 9 5" ) );
assert( 4 == ( get_evenly_div( { 5, 9, 2, 8 } ) ) );
}
REGISTER_IMPL_TEST( impl_tests );
#endif