
There is a highly organized city that has decided to assign a number to each of their departments:
Each department can have a number between 1 and 7 (inclusive).
The three department numbers are to be unique (different from each other) and must add up to 12.
The Chief of the Police doesn't like odd numbers and wants to have an even number for his department.
Write a computer program which outputsall valid combinations.
Possible output (for the 1st and 14th solutions):
--police-- --sanitation-- --fire-- 2 3 7 6 5 1
print(‘Police Sanitation Fire’)print(‘----------------------------------’)L(police) (2..6).step(2) L(sanitation) 1..7 L(fire) 1..7 I police!=sanitation & sanitation!=fire & fire!=police & police+fire+sanitation==12 print(police"\t\t"sanitation"\t\t"fire)
Police Sanitation Fire----------------------------------2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1
org100hlxih,obuf; HL = output buffermvib,2; B = policepol:mvic,1; C = sanitationsan:mvid,1; D = firefire:mova,b; Fire equal to police?cmpdjznext; If so, invalid combinationmova,c; Fire equal to sanitation?cmpdjznext; If so, invalid combinationmova,b; Total equal to 12?addcadddcpi12jnznext; If not, invalid combinationmova,b; Combination is valid, add to outputcallnummova,ccall nummova,dcallnummvim,13; Add a newline to the outputinxhmvim,10inxhnext:mvia,7; Load 7 to compare toinrd; Next fire numbercmpd; Reached the end?jncfire; If not, next fire numberinrc; Otherwise, next sanitation numbercmpc; Reached the end?jncsan; If not, next sanitation numberinrb; Increment police number twiceinrb; (twice, because it must be even)cmpb; Reached the end?jncpol ; If not, next police numbermvim,'$'; If so, we're done - add CP/M string terminatormvic,9; Print the output stringlxid,ohdrjmp5num:adi'0'; Add number A and space to the outputmovm,ainxhmvim,' 'inxhretohdr:db'P S F',13,10obuf:equ$; Output buffer goes after program
P S F2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1
cpu8086bits16org100hsection.textmovdi,obuf; Output buffermovbl,2; BL = policepol:movcl,1; CL = sanitationsan:movdl,1; DL = firefire:cmpbl,cl; Police equal to sanitation?jenext; Invalid combinationcmpbl,dl; Police equal to fire?jenext; Invalid combinationcmpcl,dl; Sanitation equal to fire?jenext; Invalid combinationmoval,bl; Total equal to 12?addal,claddal,dlcmpal,12jnenext; If not, invalid combinationmoval,bl; Combination is valid, write the three numberscallnummoval,clcallnummoval,dlcallnummovax,0A0Dh; And a newlinestoswnext:moval,7; Load 7 to compare toincdx; Increment fire numbercmpal,dl; If 7 or less,jaefire; next fire number.inccx; Otherwise, ncrement sanitation numbercmpal,cl; If 7 or less,jaesan; next sanitation numberincbx; Increment police number twiceincbx; (it must be even)cmpal,bl; If 7 or less,jaepol; next police number.movbyte[di],'$'; At the end, terminate the stringmovdx,ohdr; Tell MS-DOS to print itmovah,9int21hretnum:movah,''; Spaceaddal,'0'; Add number to outputstosw; Store number and spaceretsection.dataohdr:db'PSF',13,10; Headerobuf:equ$; Place to write output
P S F2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1
PUT 7 IN max.department.numberPUT 12 IN department.sumWRITE "police sanitation fire" /PUT 2 IN policeWHILE police <= max.department.number: FOR sanitation IN { 1 .. max.department.number }: IF sanitation <> police: PUT ( department.sum - police ) - sanitation IN fire IF fire > 0 AND fire <= max.department.number AND fire <> sanitation AND fire <> police: WRITE police>>6, sanitation>>11, fire>>5 / PUT police + 2 IN policepolice sanitation fire 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
PROC Main() BYTE p,s,f PrintE("P S F") FOR p=2 TO 6 STEP 2 DO FOR s=1 TO 7 DO FOR f=1 TO 7 DO IF p#s AND p#f AND s#f AND p+s+f=12 THEN PrintF("%B %B %B%E",p,s,f) FI OD OD ODRETURNScreenshot from Atari 8-bit computer
P S F2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1
withAda.Text_IO;procedureDepartment_NumbersisuseAda.Text_IO;beginPut_Line(" P S F");forPolicein2..6loopforSanitationin1..7loopforFirein1..7loopifPolicemod2=0andPolice+Sanitation+Fire=12andSanitation/=PoliceandSanitation/=FireandPolice/=FirethenPut_Line(Police'Image&Sanitation'Image&Fire'Image);endif;endloop;endloop;endloop;endDepartment_Numbers;
P S F 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
Tested with Agena 5.0.0 Win32
# Department numbersscope print('POLICE SANITATION FIRE'); for p from 2 to 7 by 2 do for s to 7 do if s <> p then f := 12 - p - s if f <> s and f <> p and f >= 1 and f <= 7 then printf(" %1d %1d %1d\n", p, s, f) fi fi od odepocsPOLICE SANITATION FIRE 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
integer p, s, f;p = 0;while ((p += 2) <= 7) { s = 0; while ((s += 1) <= 7) { f = 0; while ((f += 1) <= 7) { if (p + s + f == 12 && p != s && p != f && s != f) { o_form(" ~ ~ ~\n", p, s, f); } } }}As noted in the Fortran sample, once the police and sanitation departments are posited, the fire department value is fixed
BEGIN # show possible department number allocations for police, sanitation and fire departments # # the police department number must be even, all department numbers in the range 1 .. 7 # # the sum of the department numbers must be 12 # INT max department number = 7; INT department sum = 12; print( ( "police sanitation fire", newline ) ); FOR police FROM 2 BY 2 TO max department number DO FOR sanitation TO max department number DO IF sanitation /= police THEN INT fire = ( department sum - police ) - sanitation; IF fire > 0 AND fire <= max department number AND fire /= sanitation AND fire /= police THEN print( ( whole( police, -6 ) , whole( sanitation, -11 ) , whole( fire, -5 ) , newline ) ) FI FI OD ODEND
police sanitation fire 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
begin % show possible department number allocations for police, sanitation and fire departments % % the police department number must be even, all department numbers in the range 1 .. 7 % % the sum of the department numbers must be 12 % integer MAX_DEPARTMENT_NUMBER, DEPARTMENT_SUM; MAX_DEPARTMENT_NUMBER := 7; DEPARTMENT_SUM := 12; write( "police sanitation fire" ); for police := 2 step 2 until MAX_DEPARTMENT_NUMBER do begin for sanitation := 1 until MAX_DEPARTMENT_NUMBER do begin IF sanitation not = police then begin integer fire; fire := ( DEPARTMENT_SUM - police ) - sanitation; if fire > 0 and fire <= MAX_DEPARTMENT_NUMBER and fire not = sanitation and fire not = police then begin write( s_w := 0, i_w := 6, police, i_w := 11, sanitation, i_w := 5, fire ) end if_valid_combination end if_sanitation_ne_police end for_sanitation end for_policeend.
police sanitation fire 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
'PSF'⍪(⊢(⌿⍨)((∪≡⊢)¨↓∧(0=2|1⌷[2]⊢)∧12=+/))↑,⍳3/7
This prints each triplet of numbers from 1 to 7 for which:
(∪≡⊢)¨↓(0=2|1⌷[2]⊢)12=+/P S F2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1
Briefly, composing a solution from generic functions:
onrunscripton|λ|(x)scripton|λ|(y)scripton|λ|(z)ify≠zand1≤zandz≤7then{{x,y,z}asstring}else{}endifend|λ|endscriptconcatMap(result,{12-(x+y)})--Zend|λ|endscriptconcatMap(result,{1,2,3,4,5,6,7})--Yend|λ|endscriptunlines(concatMap(result,{2,4,6}))--Xendrun-- GENERIC FUNCTIONS ------------------------------------------------------------ concatMap :: (a -> [b]) -> [a] -> [b]onconcatMap(f,xs)setlstto{}setlngtolengthofxstellmReturn(f)repeatwithifrom1tolngsetlstto(lst&|λ|(contentsofitemiofxs,i,xs))endrepeatendtellreturnlstendconcatMap-- intercalate :: Text -> [Text] -> Textonintercalate(strText,lstText)set{dlm,mytext item delimiters}to{mytext item delimiters,strText}setstrJoinedtolstTextastextsetmytext item delimiterstodlmreturnstrJoinedendintercalate-- Lift 2nd class handler function into 1st class script wrapper-- mReturn :: Handler -> ScriptonmReturn(f)ifclassoffisscriptthenfelsescriptproperty|λ|:fendscriptendifendmReturn-- unlines :: [String] -> Stringonunlines(xs)intercalate(linefeed,xs)endunlines
237246264273417426435453462471615624642651
Or more generally:
-- NUMBERING CONSTRAINTS -------------------------------------------------------- options :: Int -> Int -> Int -> [(Int, Int, Int)]onoptions(lo,hi,total)setdstoenumFromTo(lo,hi)scriptXevenon|λ|(x)scriptYdistincton|λ|(y)scriptZinRangeon|λ|(z)ify≠zandlo≤zandz≤hithen{{x,y,z}}else{}endifend|λ|endscriptconcatMap(ZinRange,{total-(x+y)})-- Z IS IN RANGEend|λ|endscriptscriptnotXon|λ|(d)d≠xend|λ|endscriptconcatMap(Ydistinct,filter(notX,ds))-- Y IS NOT Xend|λ|endscriptconcatMap(Xeven,filter(myeven,ds))-- X IS EVENendoptions-- TEST -----------------------------------------------------------------------onrunsetxstooptions(1,7,12)intercalate("\n\n",¬{"(Police, Sanitation, Fire)",¬unlines(map(show,xs)),¬"Number of options: "&|length|(xs)})endrun-- GENERIC FUNCTIONS ------------------------------------------------------------ concatMap :: (a -> [b]) -> [a] -> [b]onconcatMap(f,xs)setlstto{}setlngtolengthofxstellmReturn(f)repeatwithifrom1tolngsetlstto(lst&|λ|(contentsofitemiofxs,i,xs))endrepeatendtellreturnlstendconcatMap-- enumFromTo :: Int -> Int -> [Int]onenumFromTo(m,n)ifn<mthensetdto-1elsesetdto1endifsetlstto{}repeatwithifrommtonbydsetendoflsttoiendrepeatreturnlstendenumFromTo-- even :: Int -> Booloneven(x)xmod2=0endeven-- filter :: (a -> Bool) -> [a] -> [a]onfilter(f,xs)tellmReturn(f)setlstto{}setlngtolengthofxsrepeatwithifrom1tolngsetvtoitemiofxsif|λ|(v,i,xs)thensetendoflsttovendrepeatreturnlstendtellendfilter-- intercalate :: Text -> [Text] -> Textonintercalate(strText,lstText)set{dlm,mytext item delimiters}to{mytext item delimiters,strText}setstrJoinedtolstTextastextsetmytext item delimiterstodlmreturnstrJoinedendintercalate-- length :: [a] -> Inton|length|(xs)lengthofxsend|length|-- map :: (a -> b) -> [a] -> [b]onmap(f,xs)tellmReturn(f)setlngtolengthofxssetlstto{}repeatwithifrom1tolngsetendoflstto|λ|(itemiofxs,i,xs)endrepeatreturnlstendtellendmap-- Lift 2nd class handler function into 1st class script wrapper-- mReturn :: Handler -> ScriptonmReturn(f)ifclassoffisscriptthenfelsescriptproperty|λ|:fendscriptendifendmReturn-- show :: a -> Stringonshow(e)setctoclassofeifc=listthenscriptserializedon|λ|(v)show(v)end|λ|endscript"["&intercalate(", ",map(serialized,e))&"]"elseifc=recordthenscriptshowFieldon|λ|(kv)set{k,ev}tokv"\""&k&"\":"&show(ev)end|λ|endscript"{"&intercalate(", ",¬map(showField,zip(allKeys(e),allValues(e))))&"}"elseifc=datethen"\""&iso8601Z(e)&"\""elseifc=textthen"\""&e&"\""elseif(c=integerorc=real)theneastextelseifc=classthen"null"elsetryeastextonerror("«"&castext)&"»"endtryendifendshow-- unlines :: [String] -> Stringonunlines(xs)intercalate(linefeed,xs)endunlines
(Police, Sanitation, Fire)[2, 3, 7][2, 4, 6][2, 6, 4][2, 7, 3][4, 1, 7][4, 2, 6][4, 3, 5][4, 5, 3][4, 6, 2][4, 7, 1][6, 1, 5][6, 2, 4][6, 4, 2][6, 5, 1]Number of options: 14
loop1..7'x[loop1..7'y[loop1..7'z[ifall?@[even?x12=sum@[xyz]3=sizeunique@[xyz]]->print[xyz]]]]
2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
write("--police-- --sanitation-- --fire--");for(intpolice=2;police<6;police+=2){for(intsanitation=1;sanitation<7;++sanitation){for(intfire=1;fire<7;++fire){if(police!=sanitation&&sanitation!=fire&&fire!=police&&police+fire+sanitation==12){write(" ",police,suffix=none);write(" ",sanitation,suffix=none);write(" ",fire);}}}}
perm(elements,n,opt:="",Delim:="",str:="",res:="",j:=0,dup:=""){res:=IsObject(res)?res:[],dup:=IsObject(dup)?dup:[]if(n>j)Loop,parse,elements,%Delimres:=!(InStr(str,A_LoopField)&&!(InStr(opt,"rep")))?perm(elements,n,opt,Delim,trim(strDelimA_LoopField,Delim),res,j+1,dup):reselseif!(dup[x:=perm_sort(str,Delim)]&&(InStr(opt,"comb")))dup[x]:=1,res.Insert(str)returnres,j++}perm_sort(str,Delim){Loop,Parse,str,%Delimres.=A_LoopField"`n"Sort,res,D`nreturnStrReplace(res,"`n",Delim)}
Example:
elements:="1234567",n:=3fork,vinperm(elements,n)if(SubStr(v,1,1)+SubStr(v,2,1)+SubStr(v,3,1)=12)&&(SubStr(v,1,1)/2=Floor(SubStr(v,1,1)/2))res4.=v"`n"MsgBox,262144,,%res4return
Outputs:
237246264273417426435453462471615624642651
# syntax: GAWK -f DEPARTMENT_NUMBERS.AWKBEGIN{print(" # FD PD SD")for(fire=1;fire<=7;fire++){for(police=1;police<=7;police++){for(sanitation=1;sanitation<=7;sanitation++){if(rules()~/^1+$/){printf("%2d %2d %2d %2d\n",++count,fire,police,sanitation)}}}}exit(0)}functionrules(stmt1,stmt2,stmt3){stmt1=fire!=police&&fire!=sanitation&&police!=sanitationstmt2=fire+police+sanitation==12stmt3=police%2==0return(stmt1stmt2stmt3)}
# FD PD SD 1 1 4 7 2 1 6 5 3 2 4 6 4 2 6 4 5 3 2 7 6 3 4 5 7 4 2 6 8 4 6 2 9 5 4 310 5 6 111 6 2 412 6 4 213 7 2 314 7 4 1
100REM Department numbars110PRINT"POLICE SANITATION FIRE"120FORP=2TO7STEP2130FORS=1TO7140IFS<>PTHEN150LETF=12-P-S160IFF<>SANDF<>PANDF>=1ANDF<=7THEN170PRINTUSING" # # #":P,S,F180ENDIF190ENDIF200NEXTS210NEXTP220END
POLICE SANITATION FIRE 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
TheSinclair ZX81 BASIC solution works without any changes.
print "--police-- --sanitation-- --fire--"for police = 2 to 7 step 2 for fire = 1 to 7 if fire = police then continue for sanitation = 12 - police - fire if sanitation = fire or sanitation = police then continue for if sanitation >= 1 and sanitation <= 7 then print rjust(police, 6); rjust(fire, 13); rjust(sanitation, 12) end if next firenext police
--police-- --sanitation-- --fire-- 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
10CLS20PRINT"--police-- --sanitation-- --fire--"30FORpolice=2TO7STEP240FORfire=1TO750sanitation=12-police-fire60IFsanitation>=1ANDsanitation<=7THEN70PRINTTAB(5)policeTAB(18)fireTAB(30)sanitation80endif90NEXTfire100NEXTpolice
Same as FreeBASIC entry.
print"P S F"forp=2to7step2fors=1to7ifs<>pthenletf=(12-p)-siff>0andf<=7andf<>sandf<>pthenprintp," ",s," ",fendifendifnextsnextpend
P S F2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 2
6 5 1
print "police fire sanitation"for police = 2 to 7 step 2 for fire = 1 to 7 if fire = police then [cont] sanitation = (12-police)-fire if sanitation <= 0 or sanitation > 7 or sanitation = fire or sanitation = police then [cont] print " "; police; chr$(9); fire; chr$(9); sanitation[cont] next firenext police
OpenConsole()PrintN("--police-- --sanitation-- --fire--")Forpolice=2To7Step2Forfire=1To7Iffire=police:ContinueEndIfsanitation=12-police-fireIfsanitation=fireOrsanitation=police:Continue:EndIfIfsanitation>=1Andsanitation<=7:PrintN(" "+Str(police)+#TAB$+#TAB$+Str(fire)+#TAB$+#TAB$+Str(sanitation))EndIfNextfireNextpoliceInput()CloseConsole()
Same as BASIC256 entry.
print"--police-- --sanitation-- --fire--"forpolice=2to7step2forfire=1to7iffire=policecontinuesanitation=12-police-fireifsanitation=fireorsanitation=policecontinueifsanitation>=1andsanitation<=7printpoliceusing"######",fireusing"############",sanitationusing"###########"nextfirenextpolice
Same as BASIC256 entry.
100 PRINT "Police","San.","Fire"110 FOR P=2 TO 7 STEP 2120 FOR S=1 TO 7130 IF S<>P THEN131 LET F=(12-P)-S140 IF F>0 AND F<=7 AND F<>S AND F<>P THEN PRINT P,S,F141 END IF150 NEXT160 NEXT
10REM Department numbers20PRINT"POLICE SANITATION FIRE"30FORP=2TO7STEP240FORS=1TO750IFS=PTHEN12060LETF=(12-P)-S70IFF<=0THEN12080IFF>7THEN12090IFF=STHEN120100IFF=PTHEN120110PRINTTAB(3);P;TAB(11);S;TAB(19);F120NEXTS130NEXTP140END
10REM Department numbers20PRINT"POLICE SANITATION FIRE"30FORP=2TO7STEP240FORS=1TO750IFS=PTHEN8060LETF=(12-P)-S70IFF>0ANDF<=7ANDF<>SANDF<>PTHENPRINT" ";P;" ";S;" ";F80NEXTS90NEXTP100END
POLICE SANITATION FIRE 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
Works with 1k of RAM. This program ought not to need more than minimal changes to be compatible with any old-style BASIC dialect.
10PRINT"POLICE SANITATION FIRE"20FORP=2TO7STEP230FORS=1TO740IFS=PTHENNEXTS50LETF=(12-P)-S60IFF>0ANDF<=7ANDF<>SANDF<>PTHENPRINT" ";P;" ";S;" ";F70NEXTS80NEXTP
POLICE SANITATION FIRE 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
REM >deptnumsmax_dept_num%=7dept_sum%=12PRINT"police sanitation fire"FORpolice%=2TOmax_dept_num%STEP2FORsanitation%=1TOmax_dept_num%IFsanitation%<>police%THENfire%=(dept_sum%-police%)-sanitation%IFfire%>0ANDfire%<=max_dept_num%ANDfire%<>sanitation%ANDfire%<>police%THENPRINT" ";police%;" ";sanitation%;" ";fire%ENDIFNEXTNEXTEND
police sanitation fire 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
PRINT"--police-- --sanitation-- --fire--"FORpolice=2TO7STEP2FORfire=1TO7IFfire=policeTHENGOTOcontsanitation=12-police-fireIFsanitation=fireORsanitation=policeTHENGOTOcontIFsanitation>=1ANDsanitation<=7THENPRINTUSING" # # #";police;fire;sanitationENDIFcont:NEXTfireNEXTpolice
PROGRAM"Depar/num"DECLAREFUNCTIONEntry()FUNCTIONEntry()PRINT"police sanitation fire"FORpolice=2TO7STEP2FORfire=1TO7IFfire=policeTHENGOTOcontsanitation=12-police-fireIFsanitation=fireORsanitation=policeTHENGOTOcontIFsanitation>=1ANDsanitation<=7THENPRINTTAB(3);police;TAB(13);fire;TAB(22);sanitationENDIFcont:NEXTfireNEXTpoliceENDFUNCTIONENDPROGRAM
print"P S F\n"for(p=2;p<7;p+=2)for(s=1;s<=7;s++)for(f=1;f<=7;f++)if(p!= s&& s!= f \&& p+s+f==12)print p," ",s," ",f,"\n"
P S F2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1
get "libhdr"let start() be for p=2 to 6 by 2 for s=1 to 7 for f=1 to 7 if p~=s & s~=f & p~=f & p+s+f=12 then writef("%N %N %N*N", p, s, f)2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1
Weird that such a simple task was still not implemented in C, would be great to see some really creative ( obfuscated ) solutions for this one.
#include<stdio.h>intmain(){intpolice,sanitation,fire;printf("Police Sanitation Fire\n");printf("----------------------------------");for(police=2;police<=6;police+=2){for(sanitation=1;sanitation<=7;sanitation++){for(fire=1;fire<=7;fire++){if(police!=sanitation&&sanitation!=fire&&fire!=police&&police+fire+sanitation==12){printf("\n%d\t\t%d\t\t%d",police,sanitation,fire);}}}}return0;}
Output:
Police Sanitation Fire----------------------------------2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1
usingSystem;publicclassProgram{publicstaticvoidMain(){for(intp=2;p<=7;p+=2){for(ints=1;s<=7;s++){intf=12-p-s;if(s>=f)break;if(f>7)continue;if(s==p||f==p)continue;//not even necessaryConsole.WriteLine($"Police:{p}, Sanitation:{s}, Fire:{f}");Console.WriteLine($"Police:{p}, Sanitation:{f}, Fire:{s}");}}}}
Police:2, Sanitation:3, Fire:7Police:2, Sanitation:7, Fire:3Police:2, Sanitation:4, Fire:6Police:2, Sanitation:6, Fire:4Police:4, Sanitation:1, Fire:7Police:4, Sanitation:7, Fire:1Police:4, Sanitation:2, Fire:6Police:4, Sanitation:6, Fire:2Police:4, Sanitation:3, Fire:5Police:4, Sanitation:5, Fire:3Police:6, Sanitation:1, Fire:5Police:6, Sanitation:5, Fire:1Police:6, Sanitation:2, Fire:4Police:6, Sanitation:4, Fire:2
#include<iostream>#include<iomanip>intmain(intargc,char*argv[]){intsol=1;std::cout<<"\t\tFIRE\t\tPOLICE\t\tSANITATION\n";for(intf=1;f<8;f++){for(intp=1;p<8;p++){for(ints=1;s<8;s++){if(f!=p&&f!=s&&p!=s&&!(p&1)&&(f+s+p==12)){std::cout<<"SOLUTION #"<<std::setw(2)<<sol++<<std::setw(2)<<":\t"<<std::setw(2)<<f<<"\t\t "<<std::setw(3)<<p<<"\t\t"<<std::setw(6)<<s<<"\n";}}}}return0;}
FIRE POLICE SANITATIONSOLUTION # 1: 1 4 7SOLUTION # 2: 1 6 5SOLUTION # 3: 2 4 6SOLUTION # 4: 2 6 4SOLUTION # 5: 3 2 7SOLUTION # 6: 3 4 5SOLUTION # 7: 4 2 6SOLUTION # 8: 4 6 2SOLUTION # 9: 5 4 3SOLUTION #10: 5 6 1SOLUTION #11: 6 2 4SOLUTION #12: 6 4 2SOLUTION #13: 7 2 3SOLUTION #14: 7 4 1
(let[n(range18)](for[policensanitationnfiren:when(distinct?policesanitationfire):when(even?police):when(=12(+policesanitationfire))](printlnpolicesanitationfire)))
2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1
start_up = proc () po: stream := stream$primary_output() stream$putl(po, "P S F\n- - -") for police: int in int$from_to_by(2,7,2) do for sanitation: int in int$from_to(1,7) do for fire: int in int$from_to(1,7) do if police~=sanitation & sanitation~=fire & police~=fire & police+sanitation+fire = 12 then stream$putl(po, int$unparse(police) || " " || int$unparse(sanitation) || " " || int$unparse(fire)) end end end endend start_up
P S F- - -2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1
IDENTIFICATIONDIVISION.PROGRAM-ID.DEPARTMENT-NUMBERS.DATADIVISION.WORKING-STORAGESECTION.01BANNERPIC X(24)VALUE"POLICE SANITATION FIRE".01COMBINATION.03FILLERPIC X(5)VALUESPACES.03POLICEPIC 9.03FILLERPIC X(11)VALUESPACES.03SANITATIONPIC 9.03FILLERPIC X(5)VALUESPACES.03FIREPIC 9.01TOTALPIC 99.PROCEDUREDIVISION.BEGIN.DISPLAYBANNER.PERFORMPOLICE-LOOPVARYINGPOLICEFROM2BY2UNTILPOLICEISGREATERTHAN6.STOPRUN.POLICE-LOOP.PERFORMSANITATION-LOOPVARYINGSANITATIONFROM1BY1UNTILSANITATIONISGREATERTHAN7.SANITATION-LOOP.PERFORMFIRE-LOOPVARYINGFIREFROM1BY1UNTILFIREISGREATERTHAN7.FIRE-LOOP.ADDPOLICE,SANITATION,FIREGIVINGTOTAL.IFPOLICEISNOTEQUALTOSANITATIONANDPOLICEISNOTEQUALTOFIREANDSANITATIONISNOTEQUALTOFIREANDTOTALISEQUALTO12,DISPLAYCOMBINATION.
POLICE SANITATION FIRE 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
include "cowgol.coh";typedef Dpt is int(1, 7);# print combination if validsub print_comb(p: Dpt, s: Dpt, f: Dpt) is var out: uint8[] := {'*',' ','*',' ','*','\n',0}; out[0] := p + '0'; out[2] := s + '0'; out[4] := f + '0'; if p != s and p != f and f != s and p+s+f == 12 then print(&out[0]); end if;end sub;print("P S F\n"); # headervar pol: Dpt := 2;while pol <= 7 loop var san: Dpt := 1; while san <= 7 loop var fire: Dpt := 1; while fire <= 7 loop print_comb(pol, san, fire); fire := fire + 1; end loop; san := san + 1; end loop; pol := pol + 2;end loop;P S F2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1
Almost verbatim copy of:Ruby
(1..7).to_a.each_permutation(3,true){|p|putsp.joinifp.first.even?&&p.sum==12}
237246264273417426435453462471615624642651
importstd.stdio,std.range;voidmain(){intsol=1;writeln("\t\tFIRE\t\tPOLICE\t\tSANITATION");foreach(f;iota(1,8)){foreach(p;iota(1,8)){foreach(s;iota(1,8)){if(f!=p&&f!=s&&p!=s&&!(p&1)&&(f+s+p==12)){writefln("SOLUTION #%2d:\t%2d\t\t%3d\t\t%6d",sol++,f,p,s);}}}}}
Output:
FIREPOLICESANITATIONSOLUTION # 1: 1 4 7SOLUTION # 2: 1 6 5SOLUTION # 3: 2 4 6SOLUTION # 4: 2 6 4SOLUTION # 5: 3 2 7SOLUTION # 6: 3 4 5SOLUTION # 7: 4 2 6SOLUTION # 8: 4 6 2SOLUTION # 9: 5 4 3SOLUTION #10: 5 6 1SOLUTION #11: 6 2 4SOLUTION #12: 6 4 2SOLUTION #13: 7 2 3SOLUTION #14: 7 4 1
programDepartment_numbers;{$APPTYPE CONSOLE}usesSystem.SysUtils;vari,j,k,count:Integer;beginwriteln('Police Sanitation Fire');writeln('------ ---------- ----');count:=0;i:=2;whilei<7dobeginforj:=1to7dobeginifj=ithenContinue;fork:=1to7dobeginif(k=i)or(k=j)thenContinue;ifi+j+k<>12thenContinue;writeln(format(' %d %d %d',[i,j,k]));inc(count);end;end;inc(i,2);end;writeln(#10,count,' valid combinations');readln;end.
proc main() void: byte police, sanitation, fire; writeln("Police Sanitation Fire"); for police from 2 by 2 upto 7 do for sanitation from 1 upto 7 do for fire from 1 upto 7 do if police /= sanitation and police /= fire and sanitation /= fire and police + sanitation + fire = 12 then writeln(police:6, " ", sanitation:10, " ", fire:4) fi od od odcorpPolice Sanitation Fire 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
numfmt 3 0for pol = 2 step 2 to 6 for san = 1 to 7 for fire = 1 to 7 if pol <> san and san <> fire and fire <> pol if pol + fire + san = 12 print pol & san & fire . . . ..
2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
IO.puts("P - F - S")forp<-[2,4,6],f<-1..7,s<-1..7,p!=fandp!=sandf!=sandp+f+s==12do"#{p} -#{f} -#{s}"end|>Enum.each(&IO.puts/1)
P-F-S2-3-72-4-62-6-42-7-34-1-74-2-64-3-54-5-34-6-24-7-16-1-56-2-46-4-26-5-1
Binding the namedepartmentNumbers to the following expression in the Name Manager of the Excel WorkBook:
(SeeLAMBDA: The ultimate Excel worksheet function)
departmentNumbers=validRows(LAMBDA(ab,LET(x,INDEX(ab,0,1),y,INDEX(ab,0,2),z,12-(x+y),IF(y<>z,IF(1<=z,IF(7>=z,CHOOSE({1,2,3},x,y,z),NA()),NA()),NA())))(cartesianProduct({2;4;6})(SEQUENCE(7,1,1,1))))
and also assuming the following generic bindings in the Name Manager for the WorkBook:
cartesianProduct=LAMBDA(xs,LAMBDA(ys,LET(ny,ROWS(ys),ixs,SEQUENCE(ROWS(xs)*ny,2,1,1),IF(0<>MOD(ixs,2),INDEX(xs,1+QUOTIENT(ixs,ny*2)),LET(r,MOD(QUOTIENT(ixs,2),ny),INDEX(ys,IF(0=r,ny,r)))))))validRows=LAMBDA(xs,LET(ixs,SEQUENCE(ROWS(xs),1,1,1),valids,FILTER(ixs,LAMBDA(i,NOT(ISNA(INDEX(xs,i))))(ixs)),INDEX(xs,valids,SEQUENCE(1,COLUMNS(xs)))))
The formula in cell B2 below defines a two-dimensional array which populates the rangeB2:D15:
| fx | =departmentNumbers | ||||
|---|---|---|---|---|---|
| A | B | C | D | ||
| 1 | Valid department numbers | ||||
| 2 | 2 | 3 | 7 | ||
| 3 | 2 | 4 | 6 | ||
| 4 | 2 | 6 | 4 | ||
| 5 | 2 | 7 | 3 | ||
| 6 | 4 | 1 | 7 | ||
| 7 | 4 | 2 | 6 | ||
| 8 | 4 | 3 | 5 | ||
| 9 | 4 | 5 | 3 | ||
| 10 | 4 | 6 | 2 | ||
| 11 | 4 | 7 | 1 | ||
| 12 | 6 | 1 | 5 | ||
| 13 | 6 | 2 | 4 | ||
| 14 | 6 | 4 | 2 | ||
| 15 | 6 | 5 | 1 | ||
// A function to generate department numbers. Nigel Galloway: May 2nd., 2018typedNum={Police:int;Fire:int;Sanitation:int}letfNn=n.Police%2=0&&n.Police+n.Fire+n.Sanitation=12&&n.Police<>n.Fire&&n.Police<>n.Sanitation&&n.Fire<>n.SanitationList.init(7*7*7)(funn->{Police=n%7+1;Fire=(n/7)%7+1;Sanitation=(n/49)+1})|>List.filterfN|>List.iter(printfn"%A")
{Police = 6; Fire = 5; Sanitation = 1;}{Police = 4; Fire = 7; Sanitation = 1;}{Police = 6; Fire = 4; Sanitation = 2;}{Police = 4; Fire = 6; Sanitation = 2;}{Police = 4; Fire = 5; Sanitation = 3;}{Police = 2; Fire = 7; Sanitation = 3;}{Police = 6; Fire = 2; Sanitation = 4;}{Police = 2; Fire = 6; Sanitation = 4;}{Police = 6; Fire = 1; Sanitation = 5;}{Police = 4; Fire = 3; Sanitation = 5;}{Police = 4; Fire = 2; Sanitation = 6;}{Police = 2; Fire = 4; Sanitation = 6;}{Police = 4; Fire = 1; Sanitation = 7;}{Police = 2; Fire = 3; Sanitation = 7;}USING:formattingiokernelmathmath.combinatoricsmath.rangessequencessets;IN:rosetta-code.department-numbers7[1,b]3<k-permutations>[[firsteven?][sum12=]biand]filter"{ Police, Sanitation, Fire }"printnl["%[%d, %]\n"printf]each
{ Police, Sanitation, Fire }{ 2, 3, 7 }{ 2, 4, 6 }{ 2, 6, 4 }{ 2, 7, 3 }{ 4, 1, 7 }{ 4, 2, 6 }{ 4, 3, 5 }{ 4, 5, 3 }{ 4, 6, 2 }{ 4, 7, 1 }{ 6, 1, 5 }{ 6, 2, 4 }{ 6, 4, 2 }{ 6, 5, 1 }!!'Police Sanitation Fire';!!'------|----------|----';for p = 2 to 6 by 2 do for s = 1 to 7 do for f = 1 to 7 do if p+f+s=12 and f<>p and f<>s and s<>p then !!(' ',p,' ',s,' ',f); fi od od od;Police Sanitation Fire------|----------|----
2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
01.10 F P=2,2,6;F S=1,7;F G=1,7;D 201.20 Q02.10 I (P-S)2.2,2.6,2.202.20 I (P-G)2.3,2.6,2.302.30 I (S-G)2.4,2.6,2.402.40 I (P+S+G-12)2.6,2.5,2.602.50 T %1,P,S,G,!02.60 R
= 2= 3= 7= 2= 4= 6= 2= 6= 4= 2= 7= 3= 4= 1= 7= 4= 2= 6= 4= 3= 5= 4= 5= 3= 4= 6= 2= 4= 7= 1= 6= 1= 5= 6= 2= 4= 6= 4= 2= 6= 5= 1
\ if department numbers are valid, print them on a single line:fire( pol san fir -- )2dup=if2dropdropexitthen2pickover=if2dropdropexitthenrot.swap..cr;\ tries to assign numbers with given policeno and sanitationno\ and fire = 12 - policeno - sanitationno:sanitation( pol san -- )2dup=if2dropexitthen\ no repeated numbers12over-2pick-\ calculate firenodup1<if2dropdropexitthen\ cannot be less than 1dup7>if2dropdropexitthen\ cannot be more than 7fire;\ tries to assign numbers with given policeno\ and sanitation = 1, 2, 3, ..., or 7:police( pol -- )81dodupisanitationloopdrop;\ tries to assign numbers with police = 2, 4, or 6:departmentscr\ leave input line82doipolice2+loop;
2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1 ok
This uses the ability standardised in F90 of labelling a DO-loop so that its start and end are linked by usage of the same name, with this checked by the compiler. Further, in avoiding the use of the dreaded GO TO statement, the CYCLE statement can be employed instead with the same effect, and it too can bear the same name so that it is clear which loop is involved. These names prefix the DO-loop, and so, force some additional indentation. They are not statement labels and must be unique themselves. Notably, they cannot be the same text as the name of the index variable for their DO-loop, unlike the lead given by BASIC with itsFOR I ... NEXT I arrangement.
The method is just to generate all the possibilities, discarding those that fail the specified tests. However, the requirement that the codes add up to twelve means that after the first two are chosen the third is determined, and blandly looping through all the possibilities is too much brute force and ignorance, though other collections of rules could make that bearable.
Since the modernisers of Fortran made a point of specifying that it does not specify the manner of evaluation of compound boolean expressions, specifically, that there is to be no reliance onShort-circuit_evaluation, both parts of the compound expression of the line labelled 5 "may" be evaluated even though the first may have determined the result. Prior to the introduction of LOGICAL variables with F66, one employed integer arithmetic as is demonstrated in the arithmetic-IF test of the line labelled 6. On the B6700, this usage ran faster than the corresponding boolean expression - possibly because there was no test for short-circuiting the expression when the first part of a multiply was zero...
Note that the syntax enablestwo classes of labels: the old-style numerical label in columns one to five, and the special label-like prefix of a DO-loop that is not in columns one to five. And yes, a line can have both.
INTEGERP,S,F!Department codes for Police, Sanitation, and Fire. Values 1 to 7 only.1PP:DOP=2,7,2!The police demand an even number. They're special and use violence.2SS:DOS=1,7!The sanitation department accepts any value.3IF(P.EQ.S)CYCLESS!But it must differ from the others.4F=12-(P+S)!The fire department accepts any number, but the sum must be twelve.5IF(F.LE.0.OR.F.GT.7)CYCLESS!Ensure that the only option is within range.6IF((F-S)*(F-P))7,8,7!And F is to differ from S and from P7WRITE(6,"(3I2)")P,S,F!If we get here, we have a possible set.8END DOSS!Next S9END DOPP!Next P.END!Well, that was straightforward.
Output:
2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
' version 15-08-2017' compile with: fbc -s consoleDimAsIntegerfire,police,sanitationPrint"police fire sanitation"Print"----------------------"Forpolice=2To7Step2Forfire=1To7Iffire=policeThenContinueForsanitation=12-police-fireIfsanitation=fireOrsanitation=policeThenContinueForIfsanitation>=1Andsanitation<=7ThenPrintUsing" # # # ";police;fire;sanitationEndIfNextNext' empty keyboard bufferWhileInkey<>"":WendPrint:Print"hit any key to end program"SleepEnd
police fire sanitation---------------------- 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
include "NSLog.incl"void local fn DepartmentNumbers long police, sanitation, fire printf @"Police Sanitation Fire" printf @"-------------------------------" for police = 2 to 7 step 2 for fire = 1 to 7 if ( fire = police ) then continue sanitation = 12 - police - fire if ( sanitation == fire ) or ( sanitation == police ) then continue if ( sanitation >= 1 ) and ( sanitation <= 7 ) printf @"%4d%12d%13d", police, fire, sanitation end if next nextend fnwindow 1fn DepartmentNumbersHandleEvents
Police Sanitation Fire------------------------------- 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
Fōrmulæ programs are not textual, visualization/edition of programs is done showing/manipulating structures but not text. Moreover, there can be multiple visual representations of the same program. Even though it is possible to have textual representation —i.e. XML, JSON— they are intended for storage and transfer purposes more than visualization and edition.
Programs in Fōrmulæ are created/edited online in itswebsite.
Inthis page you can see and run the program(s) related to this task and their results. You can also change either the programs or the parameters they are called with, for experimentation, but remember that these programs were created with the main purpose of showing a clear solution of the task, and they generally lack any kind of validation.
Solution
Click this link to run this code
PublicSubMain()DimsiC0,siC1,siC2AsShortDimsOutAsNewString[]DimsTempAsStringForsiC0=2To6Step2ForsiC1=1To7ForsiC2=1To7Ifsic0+siC1+siC2=12ThenIfsiC0<>siC1AndsiC1<>siC2AndsiC0<>siC2ThensOut.Add(Str(siC0)&Str(siC1)&Str(siC2))EndIfNextNextNextPrint"\tPolice\tFire\tSanitation"siC0=0ForEachsTempInsOutIncsic0Print"["&Format(Str(siC0),"00")&"]\t"&Left(sTemp,1)&"\t"&Mid(sTemp,2,1)&"\t"&Right(sTemp,1)NextEnd
Output:
Police Fire Sanitation[01] 2 3 7[02] 2 4 6[03] 2 6 4[04] 2 7 3[05] 4 1 7[06] 4 2 6[07] 4 3 5[08] 4 5 3[09] 4 6 2[10] 4 7 1[11] 6 1 5[12] 6 2 4[13] 6 4 2[14] 6 5 1
packagemainimport"fmt"funcmain(){fmt.Println("Police Sanitation Fire")fmt.Println("------ ---------- ----")count:=0fori:=2;i<7;i+=2{forj:=1;j<8;j++{ifj==i{continue}fork:=1;k<8;k++{ifk==i||k==j{continue}ifi+j+k!=12{continue}fmt.Printf(" %d %d %d\n",i,j,k)count++}}}fmt.Printf("\n%d valid combinations\n",count)}
Police Sanitation Fire------ ---------- ---- 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 114 valid combinations
classDepartmentNumbers{staticvoidmain(String[]args){println("Police Sanitation Fire")println("------ ---------- ----")intcount=0for(inti=2;i<=6;i+=2){for(intj=1;j<=7;++j){if(j==i)continuefor(intk=1;k<=7;++k){if(k==i||k==j)continueif(i+j+k!=12)continueprintln(" $i $j $k")count++}}}println()println("$count valid combinations")}}
Police Sanitation Fire------ ---------- ---- 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 114 valid combinations
10PRINT"Police Sanitation Fire"20PRINT"------|----------|----"30FORP=2TO7STEP240FORS=1TO750IFS=PTHENGOTO10060FORF=1TO770IFS=FORF=PTHENGOTO9080IFP+S+F=12THENPRINTUSING" # # #";P;F;S90NEXTF100NEXTS110NEXTP
Bare minimum:
main::IO()main=mapM_print$[2,4,6]>>=\x->[1..7]>>=\y->[12-(x+y)]>>=\z->casey/=z&&1<=z&&z<=7ofTrue->[(x,y,z)]_->[]
or, resugaring this into list comprehension format:
main::IO()main=mapM_print[(x,y,z)|x<-[2,4,6],y<-[1..7],z<-[12-(x+y)],y/=z&&1<=z&&z<=7]
Do notation:
main::IO()main=mapM_print$dox<-[2,4,6]y<-[1..7]z<-[12-(x+y)]ify/=z&&1<=z&&z<=7then[(x,y,z)]else[]
Unadorned brute force – more than enough at this small scale:
importData.List(nub)main::IO()main=letxs=[1..7]inmapM_print$xs>>=\x->xs>>=\y->xs>>=\z->[(x,y,z)|evenx&&3==length(nub[x,y,z])&&12==sum[x,y,z]]
(2,3,7)(2,4,6)(2,6,4)(2,7,3)(4,1,7)(4,2,6)(4,3,5)(4,5,3)(4,6,2)(4,7,1)(6,1,5)(6,2,4)(6,4,2)(6,5,1)
Or, more generally:
-------------------- DEPARTMENT NUMBERS ------------------options::Int->Int->Int->[(Int,Int,Int)]optionslohitotal=(\ds->filterevends>>=\x->filter(/=x)ds>>=\y->[total-(x+y)]>>=\z->[(x,y,z)|y/=z&&lo<=z&&z<=hi])[lo..hi]--------------------------- TEST -------------------------main::IO()main=letxs=options1712inputStrLn"(Police, Sanitation, Fire)\n">>mapM_printxs>>mapM_putStrLn["\nNumber of options: ",show(lengthxs)]
Reaching again for a little more syntactic sugar, the options function above could also be re-written either as a list comprehension,
options::Int->Int->Int->[(Int,Int,Int)]optionslohitotal=letds=[lo..hi]in[(x,y,z)|x<-filterevends,y<-filter(/=x)ds,letz=total-(x+y),y/=z&&lo<=z&&z<=hi]
or in Do notation:
importControl.Monad(guard)options::Int->Int->Int->[(Int,Int,Int)]optionslohitotal=letds=[lo..hi]indox<-filterevendsy<-filter(/=x)dsletz=total-(x+y)guard$y/=z&&lo<=z&&z<=hireturn(x,y,z)
(Police, Sanitation, Fire)(2,3,7)(2,4,6)(2,6,4)(2,7,3)(4,1,7)(4,2,6)(4,3,5)(4,5,3)(4,6,2)(4,7,1)(6,1,5)(6,2,4)(6,4,2)(6,5,1)Number of options: 14
The following works in both languages.
proceduremain()everywrites(center("police"|"sanitation"|"fire",12)|"\n")every((p:=2|4|6)~=(s:=1to7)~=(f:=1to7),p+s+f=12)doeverywrites(center(p|s|f,12)|"\n")end
Output:
police sanitation fire 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
Solution:
require'stats'permfrom=:,/@(perm@[{"_1comb)NB. get permutations of length x from y possible itemsalluniq=:#=#@~.NB. check items are uniqueaddto12=:12=+/NB. check items add to 12iseven=:-.@(2&|)NB. check items are evenpoliceeven=:{.@isevenNB. check first item is evenconditions=:policeeven*.addto12*.alluniqValidnums=:>:i.7NB. valid Department numbersgetDeptNums=:[:(#~conditions"1)Validnums{~permfrom
Example usage:
3getDeptNums7417471615651237273246264426462624642435453
(/:"#.2|])(#~12=+/"1)1+3comb7[load'stats'417615237246435
Note that we are only showing the distinct validcombinations here, not all validpermutations of those combinations. (Valid permutations would be: swapping the last two values in a combination, and all permutations of 2 4 6.)
Another variation would be more constraint based, blindly implementing the rules of the task and yielding all valid permutations. (Shown here with the number of possibilities at each step):
NB. 3 departments, 1..7 in each#rule1=.>,{3#<1+i.7343NB. total must be 12, numbers must be unique#rule2=.(#~((3=#@~.)*12=+/)"1)rule130NB. no odd numbers in police department (first department)#rule3=.(#~0=2|{."1)rule214rule3237246264273417426435453462471615624642651
publicclassDepartmentNumbers{publicstaticvoidmain(String[]args){System.out.println("Police Sanitation Fire");System.out.println("------ ---------- ----");intcount=0;for(inti=2;i<=6;i+=2){for(intj=1;j<=7;++j){if(j==i)continue;for(intk=1;k<=7;++k){if(k==i||k==j)continue;if(i+j+k!=12)continue;System.out.printf(" %d %d %d\n",i,j,k);count++;}}}System.out.printf("\n%d valid combinations",count);}}
Police Sanitation Fire------ ---------- ---- 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
Briefly:
(function(){'use strict';// concatMap :: (a -> [b]) -> [a] -> [b]functionconcatMap(f,xs){return[].concat.apply([],xs.map(f));};return'(Police, Sanitation, Fire)\n'+concatMap(function(x){returnconcatMap(function(y){returnconcatMap(function(z){returnz!==y&&1<=z&&z<=7?[[x,y,z]]:[];},[12-(x+y)]);},[1,2,3,4,5,6,7]);},[2,4,6]).map(JSON.stringify).join('\n');})();
(Police, Sanitation, Fire)[2,3,7][2,4,6][2,6,4][2,7,3][4,1,7][4,2,6][4,3,5][4,5,3][4,6,2][4,7,1][6,1,5][6,2,4][6,4,2][6,5,1]
Or, more generally:
(function(){'use strict';// NUMBERING CONSTRAINTS --------------------------------------------------// options :: Int -> Int -> Int -> [(Int, Int, Int)]functionoptions(lo,hi,total){varbind=flip(concatMap),ds=enumFromTo(lo,hi);returnbind(filter(even,ds),function(x){// X is even,returnbind(filter(function(d){returnd!==x;},ds),function(y){// Y is distinct from X,returnbind([total-(x+y)],function(z){// Z sums with x and y to total, and is in ds.returnz!==y&&lo<=z&&z<=hi?[[x,y,z]]:[];})})})};// GENERIC FUNCTIONS ------------------------------------------------------// concatMap :: (a -> [b]) -> [a] -> [b]functionconcatMap(f,xs){return[].concat.apply([],xs.map(f));};// enumFromTo :: Int -> Int -> [Int]functionenumFromTo(m,n){returnArray.from({length:Math.floor(n-m)+1},function(_,i){returnm+i;});};// even :: Integral a => a -> Boolfunctioneven(n){returnn%2===0;};// filter :: (a -> Bool) -> [a] -> [a]functionfilter(f,xs){returnxs.filter(f);};// flip :: (a -> b -> c) -> b -> a -> cfunctionflip(f){returnfunction(a,b){returnf.apply(null,[b,a]);};};// length :: [a] -> Intfunctionlength(xs){returnxs.length;};// map :: (a -> b) -> [a] -> [b]functionmap(f,xs){returnxs.map(f);};// show :: a -> Stringfunctionshow(x){returnJSON.stringify(x);};//, null, 2);// unlines :: [String] -> Stringfunctionunlines(xs){returnxs.join('\n');};// TEST -------------------------------------------------------------------varxs=options(1,7,12);return'(Police, Sanitation, Fire)\n\n'+unlines(map(show,xs))+'\n\nNumber of options: '+length(xs);})();
(Police, Sanitation, Fire)[2,3,7][2,4,6][2,6,4][2,7,3][4,1,7][4,2,6][4,3,5][4,5,3][4,6,2][4,7,1][6,1,5][6,2,4][6,4,2][6,5,1]Number of options: 14
Briefly:
(()=>{"use strict";constlabel="(Police, Sanitation, Fire)",solutions=[2,4,6].flatMap(x=>[1,2,3,4,5,6,7].flatMap(y=>[12-(x+y)].flatMap(z=>z!==y&&1<=z&&z<=7?[[x,y,z]]:[]))).map(JSON.stringify).join("\n");return`${label}\n${solutions}`;})();
(Police, Sanitation, Fire)[2,3,7][2,4,6][2,6,4][2,7,3][4,1,7][4,2,6][4,3,5][4,5,3][4,6,2][4,7,1][6,1,5][6,2,4][6,4,2][6,5,1]
Or, more generally, by composition of generic functions:
(()=>{"use strict";// -------------- NUMBERING CONSTRAINTS --------------// options :: Int -> Int -> Int -> [(Int, Int, Int)]constoptions=lo=>hi=>total=>{constbind=xs=>f=>xs.flatMap(f),ds=enumFromTo(lo)(hi);returnbind(ds.filter(even))(x=>bind(ds.filter(d=>d!==x))(y=>bind([total-(x+y)])(z=>(z!==y&&lo<=z&&z<=hi)?[[x,y,z]]:[])));};// ---------------------- TEST -----------------------constmain=()=>{constlabel="(Police, Sanitation, Fire)",solutions=options(1)(7)(12),n=solutions.length,list=solutions.map(JSON.stringify).join("\n");return(`${label}\n\n${list}\n\nNumber of options:${n}`);};// ---------------- GENERIC FUNCTIONS ----------------// enumFromTo :: Int -> Int -> [Int]constenumFromTo=m=>n=>Array.from({length:1+n-m},(_,i)=>m+i);// even :: Integral a => a -> Boolconsteven=n=>n%2===0;// MAIN ---returnmain();})();
(Police, Sanitation, Fire)[2,3,7][2,4,6][2,6,4][2,7,3][4,1,7][4,2,6][4,3,5][4,5,3][4,6,2][4,7,1][6,1,5][6,2,4][6,4,2][6,5,1]Number of options: 14
In this section, we present three solutions.
The first illustrates how a straightforward generate-and-test algorithm using familiar for-loops can be translated into jq.
The second illustrates how essentially the same algorithm can be written in a more economical way, without sacrificing comprehensibility.
The third illustrates how the built-in function `combinations/1' can be used to achieve greater efficiency.
The solutions in all cases are presented as a stream of JSON objects such as:
{"fire":1,"police":4,"sanitation":7}as these are self-explanatory, though it would be trivial to present them in another format. For brevity, the solutions are omitted here.
Nested for-loop
def check(fire; police; sanitation): (fire != police) and (fire != sanitation) and (police != sanitation) and (fire + police + sanitation == 12) and (police % 2 == 0);range(1;8) as $fire| range(1;8) as $police| range(1;8) as $sanitation| select( check($fire; $police; $sanitation) )| {$fire, $police, $sanitation}In Brief
{fire: range(1;8), police: range(1;8), sanitation: range(1;8)}| select( .fire != .police and .fire != .sanitation and .police != .sanitation and .fire + .police + .sanitation == 12 and .police % 2 == 0 )combinations
[range(1;8)] | combinations(3) | select( add == 12 and .[1] % 2 == 0) | {fire: .[0], police: .[1], sanitation: .[2]}usingPrintffunctionfindsolution(rng=1:7)rst=Matrix{Int}(undef,0,3)forpinrng,finrng,sinrngifp!=s!=f!=p&&p+s+f==12&&iseven(p)rst=[rst;psf]endendreturnrstendfunctionprintsolutions(sol::Matrix{Int})println(" Pol. Fire San.")println(" ---- ---- ----")forrowin1:size(sol,1)@printf("%2i |%4i%7i%7i\n",row,sol[row,:]...)endendprintsolutions(findsolution())
Pol. Fire San. ---- ---- ---- 1 | 2 7 3 2 | 2 6 4 3 | 2 4 6 4 | 2 3 7 5 | 4 7 1 6 | 4 6 2 7 | 4 5 3 8 | 4 3 5 9 | 4 2 610 | 4 1 711 | 6 5 112 | 6 4 213 | 6 2 414 | 6 1 5
// version 1.1.2funmain(args:Array<String>){println("Police Sanitation Fire")println("------ ---------- ----")varcount=0for(iin2..6step2){for(jin1..7){if(j==i)continuefor(kin1..7){if(k==i||k==j)continueif(i+j+k!=12)continueprintln(" $i $j $k")count++}}}println("\n$count valid combinations")}
Police Sanitation Fire------ ---------- ---- 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 114 valid combinations
print("Fire","Police","Sanitation")sol=0forf=1,7doforp=1,7dofors=1,7doifs+p+f==12andp%2==0andf~=pandf~=sandp~=sthenprint(f,p,s);sol=sol+1endendendendprint(string.format("\n%d solutions found",sol))
Fire Police Sanitation1 4 71 6 52 4 62 6 43 2 73 4 54 2 64 6 25 4 35 6 16 2 46 4 27 2 37 4 114 solutions found
NORMAL MODE IS INTEGER PRINT COMMENT $ POLICE SANITATION FIRE$ THROUGH LOOP, FOR P=2, 2, P.G.7 THROUGH LOOP, FOR S=1, 1, S.G.7 THROUGH LOOP, FOR F=1, 1, F.G.7 WHENEVER P.E.S .OR. P.E.F .OR. S.E.F, TRANSFER TO LOOP WHENEVER P+S+F .E. 12, PRINT FORMAT OCC, P, S, FLOOP CONTINUE VECTOR VALUES OCC = $I6,S2,I10,S2,I4*$ END OF PROGRAM
POLICE SANITATION FIRE 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
#determines if i, j, k are exclusive numbersexclusive_numbers:=proc(i,j,k)if(i=j)or(i=k)or(j=k)thenreturnfalse;endif;returntrue;endproc;#outputs all possible combinations of numbers that statisfy given conditionsdepartment_numbers:=proc()locali,j,k;printf("PoliceSanitationFire\n");forito7doforjto7dok:=12-i-j;if(k<=7)and(k>=1)and(imod2=0)andexclusive_numbers(i,j,k)thenprintf("%d%d%d\n",i,j,k);endif;enddo;enddo;endproc;department_numbers();
PoliceSanitationFire237246264273417426435453462471615624642651
Select[Permutations[Range[7],{3}],Total[#]==12&&EvenQ[First[#]]&]
{{2, 3, 7}, {2, 4, 6}, {2, 6, 4}, {2, 7, 3}, {4, 1, 7}, {4, 2, 6}, {4, 3, 5}, {4, 5, 3}, {4, 6, 2}, {4, 7, 1}, {6, 1, 5}, {6, 2, 4}, {6, 4, 2}, {6, 5, 1}}% Execute the functionsclearall;closeall;clc;sol=findsolution();disp(table(sol(:,1),sol(:,2),sol(:,3),'VariableNames',{'Pol.','Fire','San.'}))functionsol=findsolution()rng=1:7;sol=[];forp=rngforf=rngfors=rngifp~=s&&s~=f&&f~=p&&p+s+f==12&&mod(p,2)==0sol=[sol;psf];endendendendend
Pol. Fire San. ____ ____ ____ 2 7 3 2 6 4 2 4 6 2 3 7 4 7 1 4 6 2 4 5 3 4 3 5 4 2 6 4 1 7 6 5 1 6 4 2 6 2 4 6 1 5
print"Police Sanitation Fire"print"------ ---------- ----"count=0forhinrange(1,3)i=h*2forjinrange(1,7)ifj!=ithenforkinrange(1,7)ifk!=iandk!=jandi+j+k==12thenprint" "+i+" "+j+" "+kcount+=1endifendforendifendforendforprintchar(10)+count+" valid combinations"
Police Sanitation Fire------ ---------- ---- 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 114 valid combinations
MODULEDepartmentNumbers;FROMConversionsIMPORTIntToStr;FROMTerminalIMPORTWriteString,WriteLn,ReadChar;PROCEDUREWriteInt(num:INTEGER);VARstr:ARRAY[0..16]OFCHAR;BEGINIntToStr(num,str);WriteString(str);ENDWriteInt;VARi,j,k,count:INTEGER;BEGINcount:=0;WriteString("Police Sanitation Fire");WriteLn;WriteString("------ ---------- ----");WriteLn;FORi:=2TO6BY2DOFORj:=1TO7DOIFj=iTHENCONTINUE;END;FORk:=1TO7DOIF(k=i)OR(k=j)THENCONTINUE;END;IFi+j+k#12THENCONTINUE;END;WriteString(" ");WriteInt(i);WriteString(" ");WriteInt(j);WriteString(" ");WriteInt(k);WriteLn;INC(count);END;END;END;WriteLn;WriteInt(count);WriteString(" valid combinations");WriteLn;ReadChar;ENDDepartmentNumbers.
:- module department_numbers.:- interface.:- import_module io.:- pred main(io::di, io::uo) is cc_multi.:- implementation.:- import_module int, list, solutions, string.main(!IO) :- io.print_line("P S F", !IO), unsorted_aggregate(department_number, print_solution, !IO).:- pred print_solution({int, int, int}::in, io::di, io::uo) is det.print_solution({P, S, F}, !IO) :- io.format("%d %d %d\n", [i(P), i(S), i(F)], !IO).:- pred department_number({int, int, int}::out) is nondet.department_number({Police, Sanitation, Fire}) :- list.member(Police, [2, 4, 6]), list.member(Sanitation, 1 .. 7), list.member(Fire, 1 .. 7), Police \= Sanitation, Police \= Fire, Sanitation \= Fire, Police + Sanitation + Fire = 12.P S F2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1
(and(println"--police-- --sanitation-- --fire--")(dolist(lst(filter(fn(l)(and(=(uniquel)l)(=12(apply+l))(member(l0)'(246))(=2(length(intersect(restl)'(1234567))))))(map(fn(n)(mapint(explode(stringn))))(sequence111777))))(println(format" %d %d %d"lst))))
--police-- --sanitation-- --fire-- 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
Solution 2.
Let's make the flow easier to follow by using chaining (pipelining).
Example:
Instead of saying
(let(x8)(list'foo(pow2x)'bar))
we can say:
(=>>8(pow2??)(list'foo??'bar))
(foo 256 bar)
The order in which the functions are executed is the order in which they appear. I think that this makes the code easier to understand.
(define-macro(=>>_E__form_)(eval(if$args(cons'=>>(cons(list'=>>_E__form_)(args)))(begin(if(ref'??_form_)(setf(nth$it_form_)_E_))_form_))))(=>>(begin(println"--police-- --sanitation-- --fire--")(sequence111777))(map(fn(n)(mapint(explode(stringn))))??)(filter(fn(L)(and(=(uniqueL)L)(=12(apply+L))(even?(L0))(empty?(differenceL'(1234567)))))??)(dolist(lst??)(println(format" %d %d %d"lst))))
Solution 3.
Finally rising above the brute-force approach. (It's about time.)
(let(nums'(1234567))(for(police2(lastnums)2)(dolist(sanitation(differencenums(listpolice)))(let(fire(-12sanitationpolice))(if(memberfire(differencenums(listsanitationpolice)))(printlnpolice'-sanitation'-fire))))))
typeSolution=tuple[p,s,f:int]iteratorsolutions(max,total:Positive):Solution=forpincountup(2,max,2):forsin1..max:ifs==p:continueletf=total-p-siffnotin[p,s]andfin1..max:yield(p,s,f)echo"P S F"forsolinsolutions(7,12):echosol.p," ",sol.s," ",sol.f
P S F2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1
# Loop through all combinations from 1 to 7let numbers = 1..7# Create all possible unique permutations of 3 different numberslet combos = ( $numbers | each { |p| $numbers | each { |s| $numbers | each { |f| if ($p != $s and $p != $f and $s != $f) { {police: $p, sanitation: $s, fire: $f} } else { null } } } } | flatten | flatten | flatten)# Filter combinations by sum and police even requirement$combos | filter { |it| ($it.police + $it.sanitation + $it.fire) == 12 and ($it.police mod 2) == 0} | sort-by police sanitation fire╭────┬────────┬────────────┬──────╮│ # │ police │ sanitation │ fire │├────┼────────┼────────────┼──────┤│ 0 │ 2 │ 3 │ 7 ││ 1 │ 2 │ 4 │ 6 ││ 2 │ 2 │ 6 │ 4 ││ 3 │ 2 │ 7 │ 3 ││ 4 │ 4 │ 1 │ 7 ││ 5 │ 4 │ 2 │ 6 ││ 6 │ 4 │ 3 │ 5 ││ 7 │ 4 │ 5 │ 3 ││ 8 │ 4 │ 6 │ 2 ││ 9 │ 4 │ 7 │ 1 ││ 10 │ 6 │ 1 │ 5 ││ 11 │ 6 │ 2 │ 4 ││ 12 │ 6 │ 4 │ 2 ││ 13 │ 6 │ 5 │ 1 │├────┼────────┼────────────┼──────┤│ # │ police │ sanitation │ fire │╰────┴────────┴────────────┴──────╯
MODULEDepartmentNumbers;(* show possible department number allocations for police, sanitation and fire departments *)(* the police department number must be even, all department numbers in the range 1 .. 7 *)(* the sum of the department numbers must be 12 *)IMPORTOut;CONSTmaxDepartmentNumber=7;departmentSum=12;VARpolice,sanitation,fire:INTEGER;BEGINOut.String("police sanitation fire");Out.Ln;FORpolice:=2TOmaxDepartmentNumberBY2DOFORsanitation:=1TOmaxDepartmentNumberDOIFsanitation#policeTHENfire:=(departmentSum-police)-sanitation;IF(fire>0)&(fire<=maxDepartmentNumber)&(fire#sanitation)&(fire#police)THENOut.Int(police,6);Out.Int(sanitation,11);Out.Int(fire,5);Out.LnENDENDENDENDENDDepartmentNumbers.
Same as Algol 68.
class Program { function : Main(args : String[]) ~ Nil { sol := 1; "\t\tFIRE\tPOLICE\tSANITATION"->PrintLine(); for( f := 1; f < 8; f+=1; ) { for( p := 1; p < 8; p+=1; ) { for( s:= 1; s < 8; s+=1; ) { if( f <> p & f <> s & p <> s & ( p and 1 ) = 0 & ( f + s + p = 12 ) ) { "SOLUTION #{$sol}: \t{$f}\t{$p}\t{$s}"->PrintLine(); sol += 1; }; }; }; }; }}Output:
FIRE POLICE SANITATIONSOLUTION #1: 1 4 7SOLUTION #2: 1 6 5SOLUTION #3: 2 4 6SOLUTION #4: 2 6 4SOLUTION #5: 3 2 7SOLUTION #6: 3 4 5SOLUTION #7: 4 2 6SOLUTION #8: 4 6 2SOLUTION #9: 5 4 3SOLUTION #10: 5 6 1SOLUTION #11: 6 2 4SOLUTION #12: 6 4 2SOLUTION #13: 7 2 3SOLUTION #14: 7 4 1
(* * Caution: This is my first Ocaml program and anyone with Ocaml experience probably thinks it's horrible * So please don't use this as an example for "good ocaml code" see it more as * "this is what my first lines of ocaml might look like" * * The only reason im publishing this is that nobody has yet submitted an example in ocaml *)(* sfp is just a convenience to put a combination if sanitation (s) fire (f) and police (p) department in one record*)typesfp={s:int;f:int;p:int}(* Convenience Function to print a single sfp Record *)letprint_sfpe=Printf.printf"%d %d %d\n"e.se.fe.p(* Convenience Function to print a list of sfp Records*)letprint_sfp_listl=l|>List.iterprint_sfp(* Computes sum of list l *)letsuml=List.fold_left(+)0l(* checks if element e is in list l *)letelement_in_listel=l|>List.find_map(funx->ifx==ethenSome(e)elseNone)<>None(* returns a list with only the unique elements of list l *)letuniql=letrecuniq_helperaccl=matchlwith|[]->acc|h::t->ifelement_in_listhtthenuniq_helperacctelseuniq_helper(h::acc)tinuniq_helper[]l|>List.rev(* checks wheter or not list l only contains unique elements *)letis_uniql=uniql=l(* computes all combinations for a given list of sanitation, fire & police departments im not very proud of this function...maybe someone with some experience can clean it up? ;)*)letdepartment_numbersslflpl=sl|>List.fold_left(funaas->fl|>List.fold_left(funfaf->pl|>List.fold_left(funpap->ifsum[s;f;p]==12&&is_uniq[s;f;p]then{s=s;f=f;p=p}::paelsepa)[]|>List.appendfa)[]|>List.appendaa)[](* "main" function *)let_=lets=[1;2;3;4;5;6;7]inletf=[1;2;3;4;5;6;7]inletp=[2;4;6]inletresult=department_numberssfpinprint_endline"S F P";print_sfp_listresult;
S F P1 5 61 7 42 4 62 6 43 5 43 7 24 2 64 6 25 1 65 3 46 2 46 4 27 1 47 3 2
forstep(p=2,6,2, for(f=1,7, s=12-p-f; if(p!=f && p!=s && f!=s && s>0 && s<8, print(p" "f" "s))))
2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1
beginWriteln('Police Fire Sanitation');forvarp:=2to6step2doforvarf:=1to7doforvars:=1to7doif(p<>f)and(f<>s)and(p<>s)and(p+f+s=12)thenWriteln($'{p,-8}{f,-8}{s,-8}');end.
Police Fire Sanitation2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
#!/usr/bin/perlmy@even_numbers;for(1..7){if($_%2==0){push@even_numbers,$_;}}print"Police\tFire\tSanitation\n";foreachmy$police_number(@even_numbers){formy$fire_number(1..7){formy$sanitation_number(1..7){if($police_number+$fire_number+$sanitation_number==12&&$police_number!=$fire_number&&$fire_number!=$sanitation_number&&$sanitation_number!=$police_number){print"$police_number\t$fire_number\t$sanitation_number\n";}}}}
Above Code cleaned up and shortened
#!/usr/bin/perlusestrict;# Not necessary but considered good perl styleusewarnings;# this one tooprint"Police\t-\tFire\t-\tSanitation\n";formy$p(1..7)# Police Department{formy$f(1..7)# Fire Department{formy$s(1..7)# Sanitation Department{if($p%2==0&&$p+$f+$s==12&&$p!=$f&&$f!=$s&&$s!=$p&&$f!=$s)# Check if the combination of numbers is valid{print"$p\t-\t$f\t-\t$s\n";}}}}
Output:
Police-Fire-Sanitation2-3-72-4-62-6-42-7-34-1-74-2-64-3-54-5-34-6-24-7-16-1-56-2-46-4-26-5-1
#!/usr/bin/perlusestrict;# https://rosettacode.org/wiki/Department_numbersusewarnings;print"P S F\n\n";'246 1234567 1234567'=~ /(.).* \s .*?(?!\1)(.).* \s .*(?!\1)(?!\2)(.) (??{$1+$2+$3!=12}) (?{ print "@{^CAPTURE}\n" })(*FAIL)/x;
P S F2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1
#!/usr/bin/perlusestrict;# https://rosettacode.org/wiki/Department_numbersusewarnings;print"P S F\n\n";printtr/+//r,"\n"forgrep!/(\d).*\1/&&12==eval,glob'{2,4,6}'.'+{1,2,3,4,5,6,7}'x2;
Output same as with Regex
printf(1,"Police Sanitation Fire\n")printf(1,"------ ---------- ----\n")integersolutions=0forpolice=2to7by2doforsanitation=1to7doifsanitation!=policethenintegerfire=12-(police+sanitation)iffire>=1andfire<=7andfire!=policeandfire!=sanitationthenprintf(1," %d %d %d\n",{police,sanitation,fire})solutions+=1endifendifendforendforprintf(1,"\n%d solutions found\n",solutions)
Police Sanitation Fire------ ---------- ---- 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 114 solutions found
<?php$valid=0;for($police=2;$police<=6;$police+=2){for($sanitation=1;$sanitation<=7;$sanitation++){$fire=12-$police-$sanitation;if((1<=$fire)and($fire<=7)and($police!=$sanitation)and($sanitation!=$fire)){echo'Police: ',$police,', Sanitation: ',$sanitation,', Fire: ',$fire,PHP_EOL;$valid++;}}}echo$valid,' valid combinations found.',PHP_EOL;
Police: 2, Sanitation: 3, Fire: 7Police: 2, Sanitation: 4, Fire: 6Police: 2, Sanitation: 6, Fire: 4Police: 2, Sanitation: 7, Fire: 3Police: 4, Sanitation: 1, Fire: 7Police: 4, Sanitation: 2, Fire: 6Police: 4, Sanitation: 3, Fire: 5Police: 4, Sanitation: 5, Fire: 3Police: 4, Sanitation: 6, Fire: 2Police: 4, Sanitation: 7, Fire: 1Police: 6, Sanitation: 1, Fire: 5Police: 6, Sanitation: 2, Fire: 4Police: 6, Sanitation: 4, Fire: 2Police: 6, Sanitation: 5, Fire: 114 valid combinations found.
import cp.go ?=> N = 7, Sols = findall([P,S,F], department_numbers(N, P,S,F)), println(" P S F"), foreach([P,S,F] in Sols) printf("%2d %2d %2d\n",P,S,F) end, nl, printf("Number of solutions: %d\n", Sols.len), nl.go => true.department_numbers(N, Police,Sanitation,Fire) => Police :: 1..N, Sanitation :: 1..N, Fire :: 1..N, all_different([Police,Sanitation,Fire]), Police + Sanitation + Fire #= 12, Police mod 2 #= 0, solve([Police,Sanitation,Fire]).P S F 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1Number of solutions: 14
go2 => department_numbers2(N) => println(" P S F"), foreach(P in 1..N, P mod 2 == 0) foreach(S in 1..N, P != S) foreach(F in 1..N, F != P, F != S, P + S + F == 12) printf("%2d %2d %2d\n",P,S,F) end end end.import util.department_numbers3(N) => println("P S F"), L = [[P.to_string,S.to_string,F.to_string] : P in 1..N, P mod 2 == 0, S in 1..N, P != S, F in 1..N, F != P, F != S, P + S + F == 12], println(map(L,join).join("\n")).go :- println("P F S"), assign(Police, Fire, Sanitation), printf("%w %w %w\n", Police, Fire, Sanitation), fail, nl.dept(X) :- between(1, 7, X).police(X) :- member(X, [2, 4, 6]).fire(X) :- dept(X).san(X) :- dept(X). assign(A, B, C) :- police(A), fire(B), san(C), A != B, A != C, B != C, 12 is A + B + C.(de numbers NIL (co 'numbers (let N 7 (for P N (for S N (for F N (yield (list P S F)) ) ) ) ) ) )(de departments NIL (use (L) (while (setq L (numbers)) (or (bit? 1 (car L)) (= (car L) (cadr L)) (= (car L) (caddr L)) (= (cadr L) (caddr L)) (<> 12 (apply + L)) (println L) ) ) ) )(departments)
(2 3 7)(2 4 6)(2 6 4)(2 7 3)(4 1 7)(4 2 6)(4 3 5)(4 5 3)(4 6 2)(4 7 1)(6 1 5)(6 2 4)(6 4 2)(6 5 1)
(be departments (@Pol @Fire @San) (member @Pol (2 4 6)) (for @Fire 1 7) (for @San 1 7) (different @Pol @Fire) (different @Pol @San) (different @Fire @San) (^ @ (= 12 (+ (-> @Pol) (-> @Fire) (-> @San)) ) ) )
: (? (departments @Police @Fire @Sanitation)) @Police=2 @Fire=3 @Sanitation=7 @Police=2 @Fire=4 @Sanitation=6 @Police=2 @Fire=6 @Sanitation=4 @Police=2 @Fire=7 @Sanitation=3 @Police=4 @Fire=1 @Sanitation=7 @Police=4 @Fire=2 @Sanitation=6 @Police=4 @Fire=3 @Sanitation=5 @Police=4 @Fire=5 @Sanitation=3 @Police=4 @Fire=6 @Sanitation=2 @Police=4 @Fire=7 @Sanitation=1 @Police=6 @Fire=1 @Sanitation=5 @Police=6 @Fire=2 @Sanitation=4 @Police=6 @Fire=4 @Sanitation=2 @Police=6 @Fire=5 @Sanitation=1-> NIL
... under CP/M (or an emulator)
100H: /* SHOW POSSIBLE DEPARTMENT NUMBERS FOR POLICE, SANITATION AND FIRE */ /* THE POLICE DEPARTMENT NUMBER MUST BE EVEN, ALL DEPARTMENT NUMBERS */ /* MUST BE IN THE RANGE 1 .. 7 AND THE NUMBERS MUST SUM TO 12 */ /* CP/M SYSTEM CALL AND I/O ROUTINES */ BDOS: PROCEDURE( FN, ARG ); DECLARE FN BYTE, ARG ADDRESS; GOTO 5; END; PR$CHAR: PROCEDURE( C ); DECLARE C BYTE; CALL BDOS( 2, C ); END; PR$STRING: PROCEDURE( S ); DECLARE S ADDRESS; CALL BDOS( 9, S ); END; PR$NL: PROCEDURE; CALL PR$CHAR( 0DH ); CALL PR$CHAR( 0AH ); END; PR$NUMBER: PROCEDURE( N ); /* PRINTS A NUMBER IN THE MINIMUN FIELD WIDTH */ DECLARE N ADDRESS; DECLARE V ADDRESS, N$STR ( 6 )BYTE, W BYTE; V = N; W = LAST( N$STR ); N$STR( W ) = '$'; N$STR( W := W - 1 ) = '0' + ( V MOD 10 ); DO WHILE( ( V := V / 10 ) > 0 ); N$STR( W := W - 1 ) = '0' + ( V MOD 10 ); END; CALL PR$STRING( .N$STR( W ) ); END PR$NUMBER; /* TASK */ DECLARE MAX$DEPARTMENT$NUMBER LITERALLY '7'; DECLARE DEPARTMENT$SUM LITERALLY '12'; DECLARE ( POLICE, SANITATION, FIRE ) BYTE; CALL PR$STRING( .'POLICE SANITATION FIRE$' ); CALL PR$NL; DO POLICE = 2 TO MAX$DEPARTMENT$NUMBER BY 2; DO SANITATION = 1 TO MAX$DEPARTMENT$NUMBER; IF SANITATION <> POLICE THEN DO; FIRE = ( DEPARTMENT$SUM - POLICE ) - SANITATION; IF FIRE <= MAX$DEPARTMENT$NUMBER AND FIRE <> SANITATION AND FIRE <> POLICE THEN DO; CALL PR$STRING( .' $' ); CALL PR$NUMBER( POLICE ); CALL PR$STRING( .' $' ); CALL PR$NUMBER( SANITATION ); CALL PR$STRING( .' $' ); CALL PR$NUMBER( FIRE ); CALL PR$NL; END; END; END; END;EOF
POLICE SANITATION FIRE 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
print("Police Sanitation Fire")print("------ ---------- ----")localcount=0forh=1,3dolocali=h*2forj=1,7doifj!=ithenfork=1,7doifk!=iandk!=jandi+j+k==12thenprint($" {i} {j} {k}")++countendendendendendprint($"\n{count} valid combinations")
Police Sanitation Fire------ ---------- ---- 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 114 valid combinations
# Department numbersWrite-Output"POLICE SANITATION FIRE"for($p=2;$p-le7;$p+=2){for($s=1;$s-le7;$s++){if($s-ne$p){$f=12-$p-$sif(($f-ne$s)-and($f-ne$p)-and($f-ge1)-and($f-le7)){Write-Output" $p $s $f"}}}}
POLICE SANITATION FIRE 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
dept(X):-between(1,7,X).police(X):-member(X,[2,4,6]).fire(X):-dept(X).san(X):-dept(X).assign(A,B,C):-police(A),fire(B),san(C),A=\=B,A=\=C,B=\=C,12isA+B+C.main:-write("P F S"),nl,forall(assign(Police,Fire,Sanitation),format("~w ~w ~w~n",[Police,Fire,Sanitation])),halt.?-main.
P F S2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1
fromitertoolsimportpermutationsdefsolve():c,p,f,s="\\,Police,Fire,Sanitation".split(',')print(f"{c:>3}{p:^6}{f:^4}{s:^10}")c=1forp,f,sinpermutations(range(1,8),r=3):ifp+s+f==12andp%2==0:print(f"{c:>3}:{p:^6}{f:^4}{s:^10}")c+=1if__name__=='__main__':solve()
\ Police Fire Sanitation 1: 2 3 7 2: 2 4 6 3: 2 6 4 4: 2 7 3 5: 4 1 7 6: 4 2 6 7: 4 3 5 8: 4 5 3 9: 4 6 2 10: 4 7 1 11: 6 1 5 12: 6 2 4 13: 6 4 2 14: 6 5 1
Expressing the options directly and declaratively in terms of abind operator, without importingpermutations:
'''Department numbers'''fromitertoolsimport(chain)fromoperatorimport(ne)# options :: Int -> Int -> Int -> [(Int, Int, Int)]defoptions(lo,hi,total):'''Eligible integer triples.'''ds=enumFromTo(lo)(hi)returnbind(filter(even,ds))(lambdax:bind(filter(curry(ne)(x),ds))(lambday:bind([total-(x+y)])(lambdaz:[(x,y,z)]if(z!=yandlo<=z<=hi)else[])))# TEST ----------------------------------------------------# main :: IO ()defmain():'''Test'''xs=options(1,7,12)print(('Police','Sanitation','Fire'))fortplinxs:print(tpl)print('\nNo. of options: '+str(len(xs)))# GENERIC ABSTRACTIONS ------------------------------------# bind (>>=) :: [a] -> (a -> [b]) -> [b]defbind(xs):'''List monad injection operator. Two computations sequentially composed, with any value produced by the first passed as an argument to the second.'''returnlambdaf:list(chain.from_iterable(map(f,xs)))# curry :: ((a, b) -> c) -> a -> b -> cdefcurry(f):'''A curried function derived from an uncurried function.'''returnlambdaa:lambdab:f(a,b)# enumFromTo :: (Int, Int) -> [Int]defenumFromTo(m):'''Integer enumeration from m to n.'''returnlambdan:list(range(m,1+n))# even :: Int -> Booldefeven(x):'''True if x is an integer multiple of two.'''return0==x%2if__name__=='__main__':main()
('Police', 'Sanitation', 'Fire')(2, 3, 7)(2, 4, 6)(2, 6, 4)(2, 7, 3)(4, 1, 7)(4, 2, 6)(4, 3, 5)(4, 5, 3)(4, 6, 2)(4, 7, 1)(6, 1, 5)(6, 2, 4)(6, 4, 2)(6, 5, 1)No. of options: 14Nestedbind (orconcatMap) expressions (like those above) can also be translated into list comprehension notation:
'''Department numbers'''fromoperatorimportne# options :: Int -> Int -> Int -> [(Int, Int, Int)]defoptions(lo,hi,total):'''Eligible triples.'''ds=enumFromTo(lo)(hi)return[(x,y,z)forxinfilter(even,ds)foryinfilter(curry(ne)(x),ds)forzin[total-(x+y)]ify!=zandlo<=z<=hi]# Or with less tightly-constrained generation,# and more winnowing work downstream:# options2 :: Int -> Int -> Int -> [(Int, Int, Int)]defoptions2(lo,hi,total):'''Eligible triples.'''ds=enumFromTo(lo)(hi)return[(x,y,z)forxindsforyindsforzin[total-(x+y)]ifeven(x)andynotin[x,z]andlo<=z<=hi]# GENERIC -------------------------------------------------# curry :: ((a, b) -> c) -> a -> b -> cdefcurry(f):'''A curried function derived from an uncurried function.'''returnlambdaa:lambdab:f(a,b)# enumFromTo :: (Int, Int) -> [Int]defenumFromTo(m):'''Integer enumeration from m to n.'''returnlambdan:list(range(m,1+n))# even :: Int -> Booldefeven(x):'''True if x is an integer multiple of two.'''return0==x%2# unlines :: [String] -> Stringdefunlines(xs):'''A single string derived by the intercalation of a list of strings with the newline character.'''return'\n'.join(xs)# TEST ----------------------------------------------------# main :: IO ()defmain():'''Test'''xs=options(1,7,12)print(('Police','Sanitation','Fire'))print(unlines(map(str,xs)))print('\nNo. of options: '+str(len(xs)))if__name__=='__main__':main()
('Police', 'Sanitation', 'Fire')(2, 3, 7)(2, 4, 6)(2, 6, 4)(2, 7, 3)(4, 1, 7)(4, 2, 6)(4, 3, 5)(4, 5, 3)(4, 6, 2)(4, 7, 1)(6, 1, 5)(6, 2, 4)(6, 4, 2)(6, 5, 1)No. of options: 14# We start with the Police Department.# Range is the start, stop, and step. This returns only even numbers.forpinrange(2,7,2):#Next, the Sanitation Department. A simple range.forsinrange(1,7):# And now the Fire Department. After determining the Police and Fire# numbers we just have to subtract those from 12 to get the FD number.f=12-p-sifs>=f:breakeliff>7:continueprint("Police: ",p," Sanitation:",s," Fire: ",f)print("Police: ",p," Sanitation:",f," Fire: ",s)
Police: 2 Sanitation: 3 Fire: 7Police: 2 Sanitation: 7 Fire: 3Police: 2 Sanitation: 4 Fire: 6Police: 2 Sanitation: 6 Fire: 4Police: 4 Sanitation: 1 Fire: 7Police: 4 Sanitation: 7 Fire: 1Police: 4 Sanitation: 2 Fire: 6Police: 4 Sanitation: 6 Fire: 2Police: 4 Sanitation: 3 Fire: 5Police: 4 Sanitation: 5 Fire: 3Police: 6 Sanitation: 1 Fire: 5Police: 6 Sanitation: 5 Fire: 1Police: 6 Sanitation: 2 Fire: 4Police: 6 Sanitation: 4 Fire: 2
A problem this trivial is amenable to brute-force solutions such as the above, but it is a good example of the type of problem for which a constraint solver can be useful. This is how one could solve it using the `python-constraint` library:
importconstraintdepts=('police','sanitation','fire')p=constraint.Problem()forvarindepts:p.addVariable(var,range(1,8))p.addConstraint(constraint.AllDifferentConstraint())p.addConstraint(lambda*vars:sum(vars)==12,depts)p.addConstraint(lambdap:p%2==0,('police',))forsinp.getSolutions():print(s)
{'police': 6, 'fire': 5, 'sanitation': 1}{'police': 6, 'fire': 4, 'sanitation': 2}{'police': 6, 'fire': 2, 'sanitation': 4}{'police': 6, 'fire': 1, 'sanitation': 5}{'police': 4, 'fire': 6, 'sanitation': 2}{'police': 4, 'fire': 7, 'sanitation': 1}{'police': 4, 'fire': 5, 'sanitation': 3}{'police': 4, 'fire': 3, 'sanitation': 5}{'police': 4, 'fire': 2, 'sanitation': 6}{'police': 4, 'fire': 1, 'sanitation': 7}{'police': 2, 'fire': 4, 'sanitation': 6}{'police': 2, 'fire': 6, 'sanitation': 4}{'police': 2, 'fire': 7, 'sanitation': 3}{'police': 2, 'fire': 3, 'sanitation': 7}[ 2dup = iff [ 2drop drop ] done dip over swap over = iff [ 2drop drop ] done rot echo sp swap echo sp echo cr ] is fire ( pol san fir --> ) [ 2dup = iff 2drop done 12 over - dip over swap - dup 1 < iff [ 2drop drop ] done dup 7 > iff [ 2drop drop ] done fire ] is sanitation ( pol san --> ) [ 7 times [ dup i^ 1+ sanitation ] drop ] is police ( pol --> ) [ cr ' [ 2 4 6 ] witheach police ] is departments ( --> ) departments
2 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1
We solve this task in two lines. The rest of the code is to make the result look nice.
allPermutations<-setNames(expand.grid(seq(2,7,by=2),1:7,1:7),c("Police","Sanitation","Fire"))solution<-allPermutations[which(rowSums(allPermutations)==12&apply(allPermutations,1,function(x)!any(duplicated(x)))),]solution<-solution[order(solution$Police,solution$Sanitation),]row.names(solution)<-paste0("Solution #",seq_len(nrow(solution)),":")print(solution)
Police Sanitation FireSolution #1: 2 3 7Solution #2: 2 4 6Solution #3: 2 6 4Solution #4: 2 7 3Solution #5: 4 1 7Solution #6: 4 2 6Solution #7: 4 3 5Solution #8: 4 5 3Solution #9: 4 6 2Solution #10: 4 7 1Solution #11: 6 1 5Solution #12: 6 2 4Solution #13: 6 4 2Solution #14: 6 5 1
We filter the Cartesian product of the lists of candidate department numbers.
#langracket(cons'(policefiresanitation)(filter(λ(pfs)(and(not(check-duplicatespfs))(=12(apply+pfs))pfs))(cartesian-product(range282)(range18)(range18))))
'((police fire sanitation) (2 3 7) (2 4 6) (2 6 4) (2 7 3) (4 1 7) (4 2 6) (4 3 5) (4 5 3) (4 6 2) (4 7 1) (6 1 5) (6 2 4) (6 4 2) (6 5 1))
(formerly Perl 6)
for (1..7).combinations(3).grep(*.sum ==12) {for .permutations\ .grep(*.[0] %%2) {say<police fire sanitation>Z=> .list; }}
(police => 4 fire => 1 sanitation => 7)(police => 4 fire => 7 sanitation => 1)(police => 6 fire => 1 sanitation => 5)(police => 6 fire => 5 sanitation => 1)(police => 2 fire => 3 sanitation => 7)(police => 2 fire => 7 sanitation => 3)(police => 2 fire => 4 sanitation => 6)(police => 2 fire => 6 sanitation => 4)(police => 4 fire => 2 sanitation => 6)(police => 4 fire => 6 sanitation => 2)(police => 6 fire => 2 sanitation => 4)(police => 6 fire => 4 sanitation => 2)(police => 4 fire => 3 sanitation => 5)(police => 4 fire => 5 sanitation => 3)
This REXX example essentially uses brute force approach for so simple a puzzle.
/*REXX program finds/displays all possible variants of (3) department numbering puzzle.*/say'police sanitation fire'/*display simple title for the output*/say'══════ ══════════ ════'/* " head separator " " " */#=0/*number of solutions found (so far). */dop=1for7;ifp//2theniterate/*try numbers for the police department*/dos=1for7;ifs==ptheniterate/* " " " " fire " */dof=1for7;iff==stheniterate/* " " " " sanitation " */ifp+s+f\==12theniterate/*check if sum of department nums ¬= 12*/#=#+1/*bump count of the number of solutions*/saycenter(p,6)center(s,10)center(f,4)/*display one possible solution. */end/*s*/end/*f*/end/*p*/say'══════ ══════════ ════'/* " head separator " " " */say/*stick a fork in it, we're all done. */say#' solutions found.'/*also, show the # of solutions found. */
police sanitation fire══════ ══════════ ════ 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1══════ ══════════ ════14 solutions found.
sanitation= 0see "police fire sanitation" + nlfor police = 2 to 7 step 2 for fire = 1 to 7 if fire = police loop ok sanitation = 12 - police - fire if sanitation = fire or sanitation = police loop ok if sanitation >= 1 and sanitation <= 7 see " " + police + " " + fire + " " + sanitation + nl ok nextnext
Output:
police fire sanitation 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
≪ { }2 6FOR police1 7FOR sanitationIF police sanitation ≠THEN12 police - sanitation -IF DUP0 > OVER7 ≤ AND OVER police ≠ AND OVER sanitation ≠ ANDTHEN police sanitation ROT3 →ARRY +ELSE DROPENDENDNEXT2STEP DUP SIZE≫ 'PSF' STO2: { [ 2 3 7 ] [ 2 4 6 ] [ 2 6 4 ] [ 2 7 3 ] [ 4 1 7 ] [ 4 2 6 ] [ 4 3 5 ] [ 4 5 3 ] [ 4 6 2 ] [ 4 7 1 ] [ 6 1 5 ] [ 6 2 4 ] [ 6 4 2 ] [ 6 5 1 ] }1: 14(1..7).to_a.permutation(3){|p|putsp.joinifp.first.even?&&p.sum==12}
237246264273417426435453462471615624642651
externcratenum_iter;fnmain(){println!("Police Sanitation Fire");println!("----------------------");forpoliceinnum_iter::range_step(2,7,2){forsanitationin1..8{forfirein1..8{ifpolice!=sanitation&&sanitation!=fire&&fire!=police&&police+fire+sanitation==12{println!("{:6}{:11}{:4}",police,sanitation,fire);}}}}}
valdepts={(1to7).permutations.map{n=>(n(0),n(1),n(2))}.toList.distinct// All permutations of possible department numbers.filter{n=>n._1%2==0}// Keep only even numbers favored by Police Chief.filter{n=>n._1+n._2+n._3==12}// Keep only numbers that add to 12}{println("(Police, Sanitation, Fire)")println(depts.mkString("\n"))}
(Police, Sanitation, Fire)(2,3,7)(2,4,6)(2,6,4)(2,7,3)(4,1,7)(4,2,6)(4,3,5)(4,5,3)(4,6,2)(4,7,1)(6,1,5)(6,2,4)(6,4,2)(6,5,1)
@(1..7)->combinations(3,{|*a|a.sum==12||nexta.permutations{|*b|b[0].is_even||nextsay(%w(police fire sanitation)~Zb->join(" "))}})
["police", 4] ["fire", 1] ["sanitation", 7]["police", 4] ["fire", 7] ["sanitation", 1]["police", 6] ["fire", 1] ["sanitation", 5]["police", 6] ["fire", 5] ["sanitation", 1]["police", 2] ["fire", 3] ["sanitation", 7]["police", 2] ["fire", 7] ["sanitation", 3]["police", 2] ["fire", 4] ["sanitation", 6]["police", 2] ["fire", 6] ["sanitation", 4]["police", 4] ["fire", 2] ["sanitation", 6]["police", 4] ["fire", 6] ["sanitation", 2]["police", 6] ["fire", 2] ["sanitation", 4]["police", 6] ["fire", 4] ["sanitation", 2]["police", 4] ["fire", 3] ["sanitation", 5]["police", 4] ["fire", 5] ["sanitation", 3]
Functional approach:
let res = [2, 4, 6].map({x in return (1...7) .filter({ $0 != x }) .map({y -> (Int, Int, Int)? in let z = 12 - (x + y) guard y != z && 1 <= z && z <= 7 else { return nil } return (x, y, z) }).compactMap({ $0 })}).flatMap({ $0 })for result in res { print(result)}Iterative approach:
var res = [(Int, Int, Int)]()for x in [2, 4, 6] { for y in 1...7 where x != y { let z = 12 - (x + y) guard y != z && 1 <= z && z <= 7 else { continue } res.append((x, y, z)) }}for result in res { print(result)}(2, 3, 7)(2, 4, 6)(2, 6, 4)(2, 7, 3)(4, 1, 7)(4, 2, 6)(4, 3, 5)(4, 5, 3)(4, 6, 2)(4, 7, 1)(6, 1, 5)(6, 2, 4)(6, 4, 2)(6, 5, 1)
Since Tool Command Language is a multi-paradigm language, very different solutions are possible.
VERSION A - using procedures and list operations
# Procedure named ".." returns list of integers from 1 to max.proc .. max { for {set i 1} {$i <= $max} {incr i} { lappend l $i } return $l}# Procedure named "anyEqual" returns true if any elements are equal,# false otherwise.proc anyEqual l { if {[llength [lsort -unique $l]] != [llength $l]} { return 1 } return 0}# Procedure named "odd" tells whether a value is odd or not.proc odd n { expr $n %2 != 0}# Procedure named "sum" sums its parameters.proc sum args { expr [join $args +]}# Create lists of candidate numbers using proc ".."set sanitation [.. 7]set fire $sanitation# Filter even numbers for police stations (remove odd ones).set police [lmap e $sanitation { if [odd $e] continue set e}]# Try all combinations and display acceptable ones.set valid 0foreach p $police { foreach s $sanitation { foreach f $fire { # Check for equal elements in list. if [anyEqual [list $p $s $f]] continue # Check for sum of list elements. if {[sum $p $s $f] != 12} continue puts "$p $s $f" incr valid } }}puts "$valid valid combinations found."VERSION B - using simple for loops with number literals
set valid 0for {set police 2} {$police <= 6} {incr police 2} { for {set sanitation 1} {$sanitation <= 7} {incr sanitation} { if {$police == $sanitation} continue for {set fire 1} {$fire <= 7} {incr fire} { if {$police == $fire || $sanitation == $fire} continue if {[expr $police + $sanitation + $fire] != 12} continue puts "$police $sanitation $fire" incr valid } }}puts "$valid valid combinations found."VERSION C - using simple for loops with number variables
set min 1set max 7set valid 0for {set police $min} {$police <= $max} {incr police} { if {[expr $police % 2] == 1} continue ;# filter even numbers for police for {set sanitation $min} {$sanitation <= $max} {incr sanitation} { if {$police == $sanitation} continue for {set fire $min} {$fire <= $max} {incr fire} { if {$police == $fire || $sanitation == $fire} continue if {[expr $police + $sanitation + $fire] != 12} continue puts "$police $sanitation $fire" incr valid } }}puts "$valid valid combinations found."VERSION D - using list filter with lambda expressions
# Procedure named ".." returns list of integers from 1 to max.proc .. max { for {set i 1} {$i <= $max} {incr i} { lappend l $i } return $l}# Procedure named "..." returns list of n lists of integers from 1 to max.proc ... {max n} { foreach i [.. $n] { lappend result [.. $max] } return $result}# Procedure named "crossProduct" returns cross product of listsproc crossProduct {listOfLists} { set result [list [list]] foreach factor $listOfLists { set newResult {} foreach combination $result { foreach elt $factor { lappend newResult [linsert $combination end $elt] } } set result $newResult } return $result}# Procedure named "filter" filters list elements by using a # condition λ (lambda) expressionproc filter {l condition} { return [lmap el $l { if {![apply $condition $el]} continue set el }]}# Here the fun using lambda expressions begins. The following is the main program.# Set λ expressionsset λPoliceEven {_ {expr [lindex $_ 0] % 2 == 0}}set λNoEquals {_ {expr [llength [lsort -unique $_]] == [llength $_]}}set λSumIs12 {_ {expr [join $_ +] == 12}}# Create all combinations and filter acceptable onesset numbersOk [filter [filter [filter [crossProduct [... 7 3]] ${λPoliceEven}] ${λSumIs12}] ${λNoEquals}]puts [join $numbersOk \n]puts "[llength $numbersOk] valid combinations found."All four versions (A, B, C and D) produce the same result:
2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 114 valid combinations found.
PRINT "Police Sanitation Fire" PRINT "------|----------|----"10 LET P = P + 2 LET S = 020 LET S = S + 1 LET F = 0 IF S = P THEN GOTO 2030 LET F = F + 1 IF S = F THEN GOTO 30 IF F = P THEN GOTO 30 IF P + S + F = 12 THEN PRINT " ",P," ", S," ", F IF F < 7 THEN GOTO 30 IF S < 7 THEN GOTO 20 IF P < 6 THEN GOTO 10
#lang transdMainModule : { _start: (lambda (lout "Police | Sanit. | Fire") (for i in Range(1 8) where (not (mod i 2)) do (for j in Range(1 8) where (neq i j) do (for k in Range(1 8) where (and (neq i k) (neq j k)) do (if (eq (+ i j k) 12) (lout i " " j " " k))))) )}Police | Sanit. | Fire2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1
// Department numbersconsole.log(`POLICE SANITATION FIRE`);let f: number;for (var p = 2; p <= 7; p += 2) { for (var s = 1; s <= 7; s++) { if (s != p) { f = (12 - p) - s; if ((f > 0) && (f <= 7) && (f != s) && (f != p)) console.log(` ${p} ${s} ${f}`); } }}POLICE SANITATION FIRE 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
▽=0◿2⊸≡⊢▽=12⊸≡/+⧅≠3 +1⇡7
╭─ ╷ 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1 ╯
function main { set -- Police Sanitation Fire typeset -i pw=${#1} sw=${#2} fw=${#3} printf '%s' "$1" shift printf '\t%s' "$@" printf '\n' for (( p=2; p<8; p+=2 )); do for (( s=1; s<8; ++s )); do if (( s == p )); then continue fi (( f = 12 - p - s )) if (( f == s || f == p || f < 1 || f > 7 )); then continue fi printf "%${pw}d\t%${sw}d\t%${fw}d\n" "$p" "$s" "$f" done done}main "$@"PoliceSanitationFire 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
Module Module1 Sub Main() For p = 2 To 7 Step 2 For s = 1 To 7 Dim f = 12 - p - s If s >= f Then Exit For End If If f > 7 Then Continue For End If If s = p OrElse f = p Then Continue For 'not even necessary End If Console.WriteLine($"Police:{p}, Sanitation:{s}, Fire:{f}") Console.WriteLine($"Police:{p}, Sanitation:{f}, Fire:{s}") Next Next End SubEnd ModulePolice:2, Sanitation:3, Fire:7Police:2, Sanitation:7, Fire:3Police:2, Sanitation:4, Fire:6Police:2, Sanitation:6, Fire:4Police:4, Sanitation:1, Fire:7Police:4, Sanitation:7, Fire:1Police:4, Sanitation:2, Fire:6Police:4, Sanitation:6, Fire:2Police:4, Sanitation:3, Fire:5Police:4, Sanitation:5, Fire:3Police:6, Sanitation:1, Fire:5Police:6, Sanitation:5, Fire:1Police:6, Sanitation:2, Fire:4Police:6, Sanitation:4, Fire:2
fn main() { println("Police Sanitation Fire") println("------ ---------- ----") mut count := 0 for i := 2; i < 7; i += 2 { for j in 1..8 { if j == i { continue } for k in 1..8 { if k == i || k == j { continue } if i + j + k != 12 { continue } println(" $i $j $k") count++ } } } println("\n$count valid combinations")}Police Sanitation Fire------ ---------- ---- 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 114 valid combinations
10 P=220 S=130 F=140 #=0<((P=S)+(P=F)+(S=F)+(P+S+F=12=0))*11050 ?=P60 $=3270 ?=S80 $=3290 ?=F100 ?=""110 F=F+1120 #=F<8*40130 S=S+1140 #=S<8*30150 P=P+2160 #=P<8*20
2 3 72 4 62 6 42 7 34 1 74 2 64 3 54 5 34 6 24 7 16 1 56 2 46 4 26 5 1
System.print("Police Sanitation Fire")System.print("------ ---------- ----")var count = 0for (h in 1..3) { var i = h * 2 for (j in 1..7) { if (j != i) { for (k in 1..7) { if ((k != i && k != j) && (i + j + k == 12) ) { System.print(" %(i) %(j) %(k)") count = count + 1 } } } }}System.print("\n%(count) valid combinations")Police Sanitation Fire------ ---------- ---- 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 114 valid combinations
\Department numberscode CrLf=9, IntIn=10, IntOut=11, Text=12;integer P, S, F;beginText(0, "POLICE SANITATION FIRE");CrLf(0);P:= 2;while P <= 7 do begin for S:= 1, 7 do if S # P then begin F:= (12 - P) - S; if (F > 0) & (F <= 7) & (F # S) & (F # P) then begin Text(0, " "); IntOut(0, P); Text(0, " "); IntOut(0, S); Text(0, " "); IntOut(0, F); CrLf(0) end end; P:= P + 2 end;end
POLICE SANITATION FIRE 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
const std = @import("std");pub fn main() !void { const stdout = std.io.getStdOut().writer(); try stdout.writeAll("Police Sanitation Fire\n"); try stdout.writeAll("------ ---------- ----\n"); var p: usize = 2; while (p <= 7) : (p += 2) for (1..7 + 1) |s| for (1..7 + 1) |f| if (p != s and s != f and f != p and p + f + s == 12) { try stdout.print(" {d} {d} {d}\n", .{ p, s, f }); };}Police Sanitation Fire------ ---------- ---- 2 3 7 2 4 6 2 6 4 2 7 3 4 1 7 4 2 6 4 3 5 4 5 3 4 6 2 4 7 1 6 1 5 6 2 4 6 4 2 6 5 1
Using a Zigstruct to create an iterator is a common pattern in Zig.
const std = @import("std");pub fn main() !void { const stdout = std.io.getStdOut().writer(); try stdout.writeAll("Police Sanitation Fire\n"); try stdout.writeAll("------ ---------- ----\n"); var it = SolutionIterator.init(); while (it.next()) |solution| { try stdout.print( " {d} {d} {d}\n", .{ solution.police, solution.sanitation, solution.fire }, ); }}/// 3 bit unsigned (u3) limits 0 <= department <= 7const Departments = packed struct { police: u3, sanitation: u3, fire: u3,};const DepartmentsUnion = packed union { departments: Departments, together: u9,};const SolutionIterator = struct { // police is initialized to one as adding one is the first operation in next() // with the result .police == 2 (an even number) on the first pass. u: DepartmentsUnion = .{ .departments = .{ .police = 1, .sanitation = 1, .fire = 1 } }, /// init() returns an initialised structure. /// Using init() is a common Zig pattern. fn init() SolutionIterator { return SolutionIterator{}; } fn next(self: *SolutionIterator) ?Departments { if (self.u.together == 0) return null; // already completed while (true) { const ov = @addWithOverflow(self.u.together, 1); if (ov[1] == 1) { self.u.together = 0; return null; // overflowed, completed } else { self.u.together = ov[0]; // None can be zero if (self.u.departments.police == 0) self.u.departments.police = 2; // even if (self.u.departments.sanitation == 0) self.u.departments.sanitation = 1; if (self.u.departments.fire == 0) self.u.departments.fire = 1; // Police must be even if (self.u.departments.police & 1 == 1) continue; // No two can be the same if (self.u.departments.police == self.u.departments.sanitation) continue; if (self.u.departments.sanitation == self.u.departments.fire) continue; if (self.u.departments.fire == self.u.departments.police) continue; // Must total twelve (maximum sum 7 + 7 + 7 = 21 requires 5 bits) const p = @as(u5, self.u.departments.police); const s = @as(u5, self.u.departments.sanitation); const f = @as(u5, self.u.departments.fire); if (p + s + f != 12) continue; return self.u.departments; } } }};Utils.Helpers.pickNFrom(3,[1..7].walk()) // 35 combos.filter(fcn(numbers){ numbers.sum(0)==12 }) // which all sum to 12 (==5).println();L(L(1,4,7),L(1,5,6),L(2,3,7),L(2,4,6),L(3,4,5))
Note: The sum of three odd numbers is odd, so a+b+c=12 means at least one even nmber (1 even, two odd or 3 even). Futher, 2a+b=12, a,b in (2,4,6) has onesolution: a=2,b=4
For a table with repeated solutions using nested loops:
println("Police Fire Sanitation");foreach p,f,s in ([2..7,2], [1..7], [1..7]) { if((p!=s!=f) and p+f+s==12) println(p,"\t",f,"\t",s) }Police Fire Sanitation237246264273417426435453462471615624642651