You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
defmoduleSeedToLocationdodeffind_lowest_locations(input,mode)whenmodein[:seeds_as_is,:seeds_as_ranges]do[seeds_block|mapping_blocks]=String.split(input,"\n\n",trim: true)finder_fn=create_location_finder(mapping_blocks)first.._=seeds_block|>parse_seeds(mode)|>finder_fn.()|>Enum.min()firstenddefpcreate_location_finder(blocks)domappers=Enum.map(blocks,&create_mapper/1)fninput_ranges->formapper<-mappers,reduce: input_rangesdoacc->mapper.(acc)endendenddefpcreate_mapper(block)do[_preamble|rules]=String.split(block,"\n",trim: true)rules=Enum.map(rules,fnrule->[dest_start,src_start,length]=parse_numbers(rule)# create a map with ranges as keys, and an offset as value# e.g. %{98..99 => -48, 50..97 => 2, ...}{src_start..(src_start+length-1),dest_start-src_start}end)|>Enum.into(%{})fninput_ranges->Enum.flat_map(input_ranges,&map_range(&1,rules))endenddefpmap_range(input_range,rules)do# 1. process rulesresult=Enum.reduce(rules,%{},fn{rule_range,rule_offset},acc->unlessRange.disjoint?(rule_range,input_range)doMap.put(acc,intersection(input_range,rule_range),rule_offset)elseaccendend)# 2. fill in ranges not covered by the rules (offset is 0)result=difference(input_range,Map.keys(result))|>Enum.reduce(result,&Map.put(&2,&1,0))# 3. apply all offsetsEnum.map(result,fn{range,offset}->Range.shift(range,offset)end)enddefpintersection(range_1,range_2),do: max(range_1.first,range_2.first)..min(range_1.last,range_2.last)defdifference(range,ranges_to_subtract)whenis_list(ranges_to_subtract)doEnum.reduce(ranges_to_subtract,[range],fnto_subtract,acc->Enum.flat_map(acc,&difference(&1,to_subtract))|>Enum.reject(&(&1==..))end)enddefdifference(range_1,range_2)dounlessRange.disjoint?(range_1,range_2)dointersection=intersection(range_1,range_2)[]|>then(fnresult->ifintersection.first>range_1.firstdo[range_1.first..(intersection.first-1)|result]elseresultendend)|>then(fnresult->ifintersection.last<range_1.lastdo[(intersection.last+1)..range_1.last|result]elseresultendend)else[range_1]endenddefpparse_seeds("seeds: "<>fragment,mode)donumbers=parse_numbers(fragment)casemodedo:seeds_as_ranges->numbers|>Enum.chunk_every(2)|>Enum.map(fn[start,length]->start..(start+length-1)end):seeds_as_is->Enum.map(numbers,&(&1..&1))endenddefpparse_numbers(fragment),do: String.split(fragment)|>Enum.map(&String.to_integer/1)end