Post #2735401
2026-05-10 21:54 UTC
Replies (3)
-
@byorgey@mathstodon.xyz 2026-05-10 22:08
Aha, I think it must have something to do with the bijection between encodings of integer partitions as (1) nonincreasing lists of natural numbers and (2) arbitrary lists of natural numbers, witnessed by sending a nondecreasing list to its list of successive differences. For example, the partition [6,6,4,3] corresponds to [0,2,1,3]. (6 - 6 = 0, 6 - 4 = 2, etc.) I'm quite sure I have seen this bijection exploited before, perhaps in Richard Bird's book Pearls of Functional Algorithm Design? I'll have to look once I get back to my office tomorrow.
-
@oantolin@mathstodon.xyz 2026-05-10 23:06
@byorgey@mathstodon.xyz Another approach is to use binary search on each integer from 1 to maximum p to find between which two indices of p it would go. Depending on whether binary search favors the lower or upper value, that can directly give you the conjugate and is O(maximum p * log length p). In J that would be I.i.@{. @das_g@chaos.social
-
@jer_gib@functional.cafe 2026-05-11 14:01
@byorgey@mathstodon.xyz @oantolin@mathstodon.xyz @das_g@chaos.social Here's another go, I think getting to your desired running time of O(length p + maximum p). Start off by observing that it's an unfold: ``` conjugate :: [Int] -> [Int] conjugate = unfoldr strip where strip [] = Nothing strip ns = Just (length ns, takeWhile (>0) [ n - 1 | n <- ns ]) ``` This assumes that the input is a non-increasing list of positive naturals, and returns a result similarly.