Can my favourite team still become Football Champion?
Haskell (Lambdabot), 84 bytes
Thanks to @bartavelle for saving me a byte.
Without Lambdabot, add 20 bytes for import Control.Lens
plus a newline.
The function takes its arguments in the same order as described in the OP, 0-indexed. Its second argument (the list of remaining matchups) is a flat list of indexes (e.g. [1,2,4,1]
corresponds to [(Team 1 vs Team 2), (Team 4 vs Team 1)]
).
The rules are a little vague as to whether or not this is allowed. If it isn't allowed, the function can take input in the format provided by the examples – a list of tuples. In that case, add 2 bytes to this solution's score, due to replacing a:b:r
with (a,b):r
.
(!)=(+~).element
(t?(a:b:r))s=any(t?r)[a!3$s,b!3$s,b!1$a!1$s]
(t?_)s=s!!t==maximum s
Explanation:
The first line defines an infix function !
of three variables, of type (!) :: Int -> Int -> [Int] -> [Int]
, which increments the value at a given index in a list. Since, oftentimes, code is easier to understand than words (and since Haskell syntax can be weird), here's a Python translation:
def add(index, amount, items):
items[index] += amount
return items
The second line defines another infix function ?
, also of three variables (the challenge input). I'll rewrite it more readably here:
(t ? a:b:r) s = any (t ? r) [a ! 3 $ s, b ! 3 $ s, (b ! 1 $ a) ! 1 $ s]
(t ? _) s = (s !! t) == maximum s
This is a recursive implementation of exhaustive search. It recurs over the list of remaining games, branching on the three possible outcomes, and then, once the list is empty, checking whether or not our team has the maximum number of points. Again in (non-idiomatic) Python, this is:
def can_still_win(standings, games_left, our_team):
if games_left == []:
return standings[our_team] == max(standings)
team1, team2, other_games = games_left[0], games_left[1], games_left[2:]
team1Wins, team2Wins, tie = standings.copy(), standings.copy(), standings.copy()
team1Wins[team1] += 3
team2Wins[team2] += 3
tie[team1] += 1
tie[team2] += 1
return (can_still_win(team1Wins, other_games, our_team)
or can_still_win(team2Wins, other_games, our_team)
or can_still_win(tie, other_games, our_team))
Try it online!
*Sadly, TiO doesn't support Lens, so this link won't actually run.
Microsoft SQL Server, 792 bytes
CREATE FUNCTION my.f(@s XML,@m XML,@ INT)RETURNS TABLE RETURN
WITH s AS(SELECT s.value('@p','INT')p FROM @s.nodes('S')s(s)),
m AS(SELECT m.value('@i','INT')i,m.value('@j','INT')j FROM @m.nodes('M')m(m)),
a AS(SELECT ROW_NUMBER()OVER(ORDER BY-p)t,p FROM s),
b AS(SELECT p+3*(SELECT COUNT(*)FROM m WHERE t IN(i,j))o FROM a WHERE t=@),
c AS(SELECT i,j,ROW_NUMBER()OVER(ORDER BY 1/0)k FROM m WHERE @ NOT IN(i,j)),
d AS(SELECT COUNT(*)u,POWER(3,COUNT(*))-1 v FROM c UNION ALL SELECT u,v-1 FROM d WHERE v>0),
e AS(SELECT v,u,v/3 q,v%3 r FROM d UNION ALL SELECT v,u-1,q/3,q%3 FROM e WHERE u>1),
f AS(SELECT v,p+SUM(IIF(t=i,r,(2-r))%3*3/2)s FROM a,c,e WHERE t IN(i,j)AND k=u GROUP BY v,t,p),
g AS(SELECT MAX(s)x FROM f GROUP BY v)SELECT SUM(IIF(o<ISNULL(x,p),0,1))f FROM a,(b OUTER APPLY g)WHERE t=1;
The function returns 0 for a false outcome and more than 0 for a truthy one.
The whole snippet:
SET NOCOUNT ON;
--USE tempdb;
USE rextester;
GO
IF SCHEMA_ID('my') IS NULL EXEC('CREATE SCHEMA my');
ELSE BEGIN
IF OBJECT_ID('my.f', 'IF') IS NOT NULL DROP FUNCTION my.f;
IF OBJECT_ID('my.s', 'U') IS NOT NULL DROP TABLE my.s;
IF OBJECT_ID('my.m', 'U') IS NOT NULL DROP TABLE my.m;
IF OBJECT_ID('my.c', 'U') IS NOT NULL DROP TABLE my.c;
END;
GO
CREATE TABLE my.c( -- Test cases
c INT PRIMARY KEY CLUSTERED CHECK(c > 0), -- Test Case Id
n INT CHECK(n > 0), -- Current position of the team of interest
);
CREATE TABLE my.s( -- Standings
a INT FOREIGN KEY REFERENCES my.c(c) CHECK(a > 0), -- Test cAse Id
p INT CHECK(p > 0) -- Team pts
);
CREATE TABLE my.m( -- Matches
s INT FOREIGN KEY REFERENCES my.c(c) CHECK(s > 0), -- Test caSe Id
i INT CHECK(i > 0), -- Team i
j INT CHECK(j > 0), -- Team j
CHECK(i != j)
);
GO
INSERT my.c(c, n) VALUES (1, 2), (2, 1), (3, 3), (4, 2), (5, 2), (6, 1), (7, 2);
INSERT my.s(a, p) VALUES (1, 93), (1, 86), (1, 78), (1, 76), (1, 75),
(2, 50), (3, 10), (3, 10), (3, 10), (4, 15), (4, 10), (4, 8),
(5, 10), (5, 9), (5, 8), (6, 10), (6, 9), (6, 9), (7, 21), (7, 12), (7, 11);
INSERT my.m(s, i, j) VALUES (1, 1, 2), (1, 4, 3), (1, 2, 3), (1, 3, 2), (1, 1, 2),
(4, 2, 3), (4, 1, 3), (4, 1, 3),(4, 3, 1), (4, 2, 1), (6, 2, 3), (6, 3, 2),
(7, 2, 1), (7, 1, 2), (7, 2, 3), (7, 1, 3), (7, 1, 3), (7, 3, 1), (7, 3, 1);
GO
CREATE FUNCTION my.f(@s XML,@m XML,@ INT)RETURNS TABLE RETURN
WITH s AS(SELECT s.value('@p','INT')p FROM @s.nodes('S')s(s)),
m AS(SELECT m.value('@i','INT')i,m.value('@j','INT')j FROM @m.nodes('M')m(m)),
a AS(SELECT ROW_NUMBER()OVER(ORDER BY-p)t,p FROM s),
b AS(SELECT p+3*(SELECT COUNT(*)FROM m WHERE t IN(i,j))o FROM a WHERE t=@),
c AS(SELECT i,j,ROW_NUMBER()OVER(ORDER BY 1/0)k FROM m WHERE @ NOT IN(i,j)),
d AS(SELECT COUNT(*)u,POWER(3,COUNT(*))-1 v FROM c UNION ALL SELECT u,v-1 FROM d WHERE v>0),
e AS(SELECT v,u,v/3 q,v%3 r FROM d UNION ALL SELECT v,u-1,q/3,q%3 FROM e WHERE u>1),
f AS(SELECT v,p+SUM(IIF(t=i,r,(2-r))%3*3/2)s FROM a,c,e WHERE t IN(i,j)AND k=u GROUP BY v,t,p),
g AS(SELECT MAX(s)x FROM f GROUP BY v)SELECT SUM(IIF(o<ISNULL(x,p),0,1))f FROM a,(b OUTER APPLY g)WHERE t=1;
GO
SELECT c, f
FROM my.c
OUTER APPLY(SELECT p FROM my.s S WHERE a = c FOR XML AUTO)S(s)
OUTER APPLY(SELECT i, j FROM my.m M WHERE s = c FOR XML AUTO)M(m)
OUTER APPLY my.f(s, m, n)
ORDER BY c
OPTION(MAXRECURSION 0);
Check It Online!