Project · Interview practice

Ranked keyset page contract

Fourteen checks for a deterministic composite order, bounded pages, continuation and invalid assumptions.

All C# source files below are loaded together in the playground. Files written by a run live in its virtual directory.

Interview.csproj

<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net9.0</TargetFramework><LangVersion>13.0</LangVersion><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable></PropertyGroup></Project>

Program.cs

Console.WriteLine(PageChecks.Run()+" pagination checks passed");

Domain/RankedPages.cs

public sealed record RankedRow(int Score,int Id);
public static class RankedPages {
    public static int Compare(RankedRow a,RankedRow b){int score=b.Score.CompareTo(a.Score);return score!=0?score:a.Id.CompareTo(b.Id);}
    public static RankedRow[] Page(IEnumerable<RankedRow> rows,RankedRow? after,int size){
        if(size is <1 or >3)throw new ArgumentOutOfRangeException(nameof(size));
        var snapshot=rows.ToArray();if(snapshot.Select(x=>x.Id).Distinct().Count()!=snapshot.Length)throw new ArgumentException("IDs must be unique");
        return snapshot.Where(x=>after is null || Compare(x,after)>0).OrderBy(x=>x,Comparer<RankedRow>.Create(Compare)).Take(size).ToArray();
    }
}

Checks/PageChecks.cs

public static class PageChecks {
    public static int Run(){int checks=0;void Check(bool ok,string name){if(!ok)throw new InvalidOperationException(name);checks++;}
        var rows=new[]{new RankedRow(5,3),new RankedRow(9,2),new RankedRow(9,1),new RankedRow(-1,4)};
        var first=RankedPages.Page(rows,null,2);Check(first.Select(x=>x.Id).SequenceEqual(new[]{1,2}),"tie order");
        var next=RankedPages.Page(rows,first[^1],2);Check(next.Select(x=>x.Id).SequenceEqual(new[]{3,4}),"continuation");
        Check(RankedPages.Page(rows,next[^1],2).Length==0,"end");Check(RankedPages.Page(Array.Empty<RankedRow>(),null,1).Length==0,"empty");
        Check(RankedPages.Page(rows,null,1).Length==1,"bounded output");Check(rows[0].Id==3,"source retained");
        foreach(int size in new[]{0,-1,4}){bool rejected=false;try{RankedPages.Page(rows,null,size);}catch(ArgumentOutOfRangeException){rejected=true;}Check(rejected,"limit");}
        bool duplicate=false;try{RankedPages.Page(new[]{new RankedRow(1,1),new RankedRow(2,1)},null,2);}catch(ArgumentException){duplicate=true;}Check(duplicate,"duplicate ID");
        Check(RankedPages.Compare(new(int.MaxValue,1),new(int.MinValue,2))<0,"score overflow boundary");
        Check(RankedPages.Compare(new(5,1),new(5,1))==0,"reflexive");
        Check(RankedPages.Compare(new(5,2),new(5,1))>0,"secondary direction");
        var all=new List<int>();RankedRow? cursor=null;while(true){var page=RankedPages.Page(rows,cursor,1);if(page.Length==0)break;all.Add(page[0].Id);cursor=page[0];}
        Check(all.SequenceEqual(new[]{1,2,3,4}),"all pages match independent expected order");return checks;
    }
}