Department numbers

From Rosetta Code
Revision as of 11:36, 3 June 2017 by Tigerofdarkness (talk | contribs) (→‎{{header|ALGOL 68}}: Simplified using Dinosaur's observation that once we have a possible values for two departments, there can be only one possible value for the third)
Task
Department numbers
You are encouraged to solve this task according to the task description, using any language you may know.

There is a highly organized city that has decided to assign a number to each of their departments:

  •   police department
  •   sanitation department
  •   fire department


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 the number 12.

The Chief of the Police doesn't like odd numbers and wants to have an even number for his department.


Task

Write a program which outputs all valid combinations.


Possible output:

1 2 9
5 3 4

ALGOL 68

As noted in the Fortran sample, once the police and sanitation departments are posited, the fire department value is fixed <lang algol68>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
   OD

END</lang>

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

AppleScript

Briefly, composing a solution from generic functions:

<lang AppleScript>on run

   script
       on |λ|(x)
           script
               on |λ|(y)
                   script
                       on |λ|(z)
                           if y ≠ z and 1 ≤ z and z ≤ 7 then
                               {{x, y, z} as string}
                           else
                               {}
                           end if
                       end |λ|
                   end script
                   
                   concatMap(result, {12 - (x + y)}) --Z
               end |λ|
           end script
           
           concatMap(result, {1, 2, 3, 4, 5, 6, 7}) --Y
       end |λ|
   end script
   
   unlines(concatMap(result, {2, 4, 6})) --X

end run


-- GENERIC FUNCTIONS ----------------------------------------------------------

-- concatMap :: (a -> [b]) -> [a] -> [b] on concatMap(f, xs)

   set lst to {}
   set lng to length of xs
   tell mReturn(f)
       repeat with i from 1 to lng
           set lst to (lst & |λ|(contents of item i of xs, i, xs))
       end repeat
   end tell
   return lst

end concatMap

-- intercalate :: Text -> [Text] -> Text on intercalate(strText, lstText)

   set {dlm, my text item delimiters} to {my text item delimiters, strText}
   set strJoined to lstText as text
   set my text item delimiters to dlm
   return strJoined

end intercalate

-- Lift 2nd class handler function into 1st class script wrapper -- mReturn :: Handler -> Script on mReturn(f)

   if class of f is script then
       f
   else
       script
           property |λ| : f
       end script
   end if

end mReturn

-- unlines :: [String] -> String on unlines(xs)

   intercalate(linefeed, xs)

end unlines</lang>

Output:
237
246
264
273
417
426
435
453
462
471
615
624
642
651

Or more generally:

Translation of: JavaScript
Translation of: Haskell

<lang AppleScript>-- NUMBERING CONSTRAINTS ------------------------------------------------------

-- options :: Int -> Int -> Int -> [(Int, Int, Int)] on options(lo, hi, total)

   set ds to enumFromTo(lo, hi)
   
   script Xeven
       on |λ|(x)
           script Ydistinct
               on |λ|(y)
                   script ZinRange
                       on |λ|(z)
                           if y ≠ z and lo ≤ z and z ≤ hi then
                               Template:X, y, z
                           else
                               {}
                           end if
                       end |λ|
                   end script
                   
                   concatMap(ZinRange, {total - (x + y)}) -- Z IS IN RANGE
               end |λ|
           end script
           
           script notX
               on |λ|(d)
                   d ≠ x
               end |λ|
           end script
           
           concatMap(Ydistinct, filter(notX, ds)) -- Y IS NOT X
       end |λ|
   end script
   
   concatMap(Xeven, filter(my even, ds)) -- X IS EVEN

end options


-- TEST ----------------------------------------------------------------------- on run

   set xs to options(1, 7, 12)
   
   intercalate("\n\n", ¬
       {"(Police, Sanitation, Fire)", ¬
           unlines(map(show, xs)), ¬
           "Number of options: " & |length|(xs)})

end run


-- GENERIC FUNCTIONS ----------------------------------------------------------

-- concatMap :: (a -> [b]) -> [a] -> [b] on concatMap(f, xs)

   set lst to {}
   set lng to length of xs
   tell mReturn(f)
       repeat with i from 1 to lng
           set lst to (lst & |λ|(contents of item i of xs, i, xs))
       end repeat
   end tell
   return lst

end concatMap

-- enumFromTo :: Int -> Int -> [Int] on enumFromTo(m, n)

   if n < m then
       set d to -1
   else
       set d to 1
   end if
   set lst to {}
   repeat with i from m to n by d
       set end of lst to i
   end repeat
   return lst

end enumFromTo

-- even :: Int -> Bool on even(x)

   x mod 2 = 0

end even

-- filter :: (a -> Bool) -> [a] -> [a] on filter(f, xs)

   tell mReturn(f)
       set lst to {}
       set lng to length of xs
       repeat with i from 1 to lng
           set v to item i of xs
           if |λ|(v, i, xs) then set end of lst to v
       end repeat
       return lst
   end tell

end filter

-- intercalate :: Text -> [Text] -> Text on intercalate(strText, lstText)

   set {dlm, my text item delimiters} to {my text item delimiters, strText}
   set strJoined to lstText as text
   set my text item delimiters to dlm
   return strJoined

end intercalate

-- length :: [a] -> Int on |length|(xs)

   length of xs

end |length|

-- map :: (a -> b) -> [a] -> [b] on map(f, xs)

   tell mReturn(f)
       set lng to length of xs
       set lst to {}
       repeat with i from 1 to lng
           set end of lst to |λ|(item i of xs, i, xs)
       end repeat
       return lst
   end tell

end map

-- Lift 2nd class handler function into 1st class script wrapper -- mReturn :: Handler -> Script on mReturn(f)

   if class of f is script then
       f
   else
       script
           property |λ| : f
       end script
   end if

end mReturn

-- show :: a -> String on show(e)

   set c to class of e
   if c = list then
       script serialized
           on |λ|(v)
               show(v)
           end |λ|
       end script
       
       "[" & intercalate(", ", map(serialized, e)) & "]"
   else if c = record then
       script showField
           on |λ|(kv)
               set {k, ev} to kv
               "\"" & k & "\":" & show(ev)
           end |λ|
       end script
       
       "{" & intercalate(", ", ¬
           map(showField, zip(allKeys(e), allValues(e)))) & "}"
   else if c = date then
       "\"" & iso8601Z(e) & "\""
   else if c = text then
       "\"" & e & "\""
   else if (c = integer or c = real) then
       e as text
   else if c = class then
       "null"
   else
       try
           e as text
       on error
           ("«" & c as text) & "»"
       end try
   end if

end show

-- unlines :: [String] -> String on unlines(xs)

   intercalate(linefeed, xs)

end unlines</lang>

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]

Number of options: 14

C++

<lang cpp>

  1. include <iostream>
  2. include <iomanip>

int main( int argc, char* argv[] ) {

   int sol = 1;
   std::cout << "\t\tFIRE\t\tPOLICE\t\tSANITATION\n";
   for( int f = 1; f < 8; f++ ) {
       for( int p = 1; p < 8; p++ ) {
           for( int s = 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";
               }
           }
       }
   }
   return 0;

}</lang>

Output:
                FIRE            POLICE          SANITATION
SOLUTION # 1:    1                 4                 7
SOLUTION # 2:    1                 6                 5
SOLUTION # 3:    2                 4                 6
SOLUTION # 4:    2                 6                 4
SOLUTION # 5:    3                 2                 7
SOLUTION # 6:    3                 4                 5
SOLUTION # 7:    4                 2                 6
SOLUTION # 8:    4                 6                 2
SOLUTION # 9:    5                 4                 3
SOLUTION #10:    5                 6                 1
SOLUTION #11:    6                 2                 4
SOLUTION #12:    6                 4                 2
SOLUTION #13:    7                 2                 3
SOLUTION #14:    7                 4                 1

Haskell

Bare minimum: <lang haskell>main :: IO () main =

 mapM_ print $
 [2, 4, 6] >>=
 \x ->
    [1 .. 7] >>=
    \y ->
       [12 - (x + y)] >>=
       \z ->
          case y /= z && 1 <= z && z <= 7 of
            True -> [(x, y, z)]
            _ -> []</lang>

or, resugaring this into list comprehension format: <lang Haskell>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 ]</lang>

or Do notation: <lang Haskell>main :: IO () main =

 mapM_ print $
 do x <- [2, 4, 6]
    y <- [1 .. 7]
    z <- [12 - (x + y)]
    if y /= z && 1 <= z && z <= 7
      then [(x, y, z)]
      else []</lang>
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)

Or, more generally: <lang Haskell>options :: Int -> Int -> Int -> [(Int, Int, Int)] options lo hi total =

 (\ds ->
     filter even ds >>=
     \x ->
        filter (/= x) ds >>=
        \y ->
           [total - (x + y)] >>=
           \z ->
              case y /= z && lo <= z && z <= hi of
                True -> [(x, y, z)]
                _ -> [])
   [lo .. hi]

-- TEST ----------------------------------------------------------------------- main :: IO () main = do

 let xs = options 1 7 12
 putStrLn "(Police, Sanitation, Fire)\n"
 mapM_ print xs
 mapM_ putStrLn ["\nNumber of options: ", show (length xs)]</lang>

Reaching again for a little more syntactic sugar, the options function above could also be re-written either as a list comprehension, <lang Haskell>options :: Int -> Int -> Int -> [(Int, Int, Int)] options lo hi total =

 let ds = [lo .. hi]
 in [ (x, y, z)
    | x <- filter even ds 
    , y <- filter (/= x) ds 
    , let z = total - (x + y) 
    , y /= z && lo <= z && z <= hi ]</lang>

or in Do notation: <lang haskell>import Control.Monad (guard)

options :: Int -> Int -> Int -> [(Int, Int, Int)] options lo hi total =

 let ds = [lo .. hi]
 in do x <- filter even ds
       y <- filter (/= x) ds
       let z = total - (x + y)
       guard $ y /= z && lo <= z && z <= hi
       return (x, y, z)</lang>
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)

Number of options: 
14

Fortran

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 its FOR 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 on Short-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 enables two 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. <lang Fortran> INTEGER P,S,F !Department codes for Police, Sanitation, and Fire. Values 1 to 7 only.

   1  PP:DO P = 2,7,2	!The police demand an even number. They're special and use violence.
   2   SS:DO S = 1,7		!The sanitation department accepts any value.
   3        IF (P.EQ.S) CYCLE SS	!But it must differ from the others.
   4        F = 12 - (P + S)		!The fire department accepts any number, but the sum must be twelve.
   5        IF (F.LE.0 .OR. F.GT.7) CYCLE SS	!Ensure that the only option is within range.
   6        IF ((F - S)*(F - P)) 7,8,7		!And F is to differ from S and from P
   7        WRITE (6,"(3I2)") P,S,F		!If we get here, we have a possible set.
   8      END DO SS		!Next S
   9    END DO PP	!Next P.
     END	!Well, that was straightforward.</lang>

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

Gambas

<lang gambas>Public Sub Main() Dim siC0, siC1, siC2 As Short Dim sOut As New String[] Dim sTemp As String

For siC0 = 2 To 6 Step 2

 For siC1 = 1 To 7
   For siC2 = 1 To 7
     If sic0 + siC1 + siC2 = 12 Then
       If siC0 <> siC1 And siC1 <> siC2 And siC0 <> siC2 Then sOut.Add(Str(siC0) & Str(siC1) & Str(siC2))
     End If
   Next
 Next

Next

Print "\tPolice\tFire\tSanitation" siC0 = 0

For Each sTemp In sOut

 Inc sic0
 Print "[" & Format(Str(siC0), "00") & "]\t" & Left(sTemp, 1) & "\t" & Mid(sTemp, 2, 1) & "\t" & Right(sTemp, 1)

Next

End</lang> 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

J

Solution: <lang j>require 'stats' permfrom=: ,/@(perm@[ {"_ 1 comb) NB. get permutations of length x from y possible items

alluniq=: # = #@~. NB. check items are unique addto12=: 12 = +/ NB. check items add to 12 iseven=: -.@(2&|) NB. check items are even policeeven=: {.@iseven NB. check first item is even conditions=: policeeven *. addto12 *. alluniq

Validnums=: >: i.7 NB. valid Department numbers

getDeptNums=: [: (#~ conditions"1) Validnums {~ permfrom</lang> Example usage: <lang j> 3 getDeptNums 7 4 1 7 4 7 1 6 1 5 6 5 1 2 3 7 2 7 3 2 4 6 2 6 4 4 2 6 4 6 2 6 2 4 6 4 2 4 3 5 4 5 3</lang>

JavaScript

ES5

Briefly: <lang JavaScript>(function () {

   'use strict';
   // concatMap :: (a -> [b]) -> [a] -> [b]
   function concatMap(f, xs) {
       return [].concat.apply([], xs.map(f));
   };
   return '(Police, Sanitation, Fire)\n' +
       concatMap(function (x) {
           return concatMap(function (y) {
               return concatMap(function (z) {
                   return z !== 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');

})();</lang>

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]

Or, more generally:

Translation of: Haskell

<lang JavaScript>(function () {

   'use strict';
   // NUMBERING CONSTRAINTS --------------------------------------------------
   // options :: Int -> Int -> Int -> [(Int, Int, Int)]
   function options(lo, hi, total) {
       var bind = flip(concatMap),
           ds = enumFromTo(lo, hi);
       return bind(filter(even, ds),
           function (x) { // X is even,
               return bind(filter(function (d) { return d !== x; }, ds),
           function (y) { // Y is distinct from X,
               return bind([total - (x + y)],
           function (z) { // Z sums with x and y to total, and is in ds.
               return z !== y && lo <= z && z <= hi ? [
                   [x, y, z]
               ] : [];
           })})})};
   // GENERIC FUNCTIONS ------------------------------------------------------
   // concatMap :: (a -> [b]) -> [a] -> [b]
   function concatMap(f, xs) {
       return [].concat.apply([], xs.map(f));
   };
   // enumFromTo :: Int -> Int -> [Int]
   function enumFromTo(m, n) {
       return Array.from({
           length: Math.floor(n - m) + 1
       }, function (_, i) {
           return m + i;
       });
   };
   // even :: Integral a => a -> Bool
   function even(n) {
       return n % 2 === 0;
   };
   // filter :: (a -> Bool) -> [a] -> [a]
   function filter(f, xs) {
       return xs.filter(f);
   };
   // flip :: (a -> b -> c) -> b -> a -> c
   function flip(f) {
       return function (a, b) {
           return f.apply(null, [b, a]);
       };
   };
   // length :: [a] -> Int
   function length(xs) {
       return xs.length;
   };
   // map :: (a -> b) -> [a] -> [b]
   function map(f, xs) {
       return xs.map(f);
   };
   // show :: a -> String
   function show(x) {
       return JSON.stringify(x);
   }; //, null, 2);
   // unlines :: [String] -> String
   function unlines(xs) {
       return xs.join('\n');
   };
   // TEST -------------------------------------------------------------------
   var xs = options(1, 7, 12);
   return '(Police, Sanitation, Fire)\n\n' +
       unlines(map(show, xs)) + '\n\nNumber of options: ' + length(xs);

})();</lang>

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]

Number of options: 14

ES6

Briefly: <lang JavaScript>(() => {

   // concatMap :: (a -> [b]) -> [a] -> [b]
   const concatMap = (f, xs) => [].concat.apply([], xs.map(f));
   return '(Police, Sanitation, Fire)\n' +
       concatMap(x =>
           concatMap(y =>
               concatMap(z =>
                   z !== 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');

})();</lang>

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]

Or, more generally, by composition of generic functions:

Translation of: Haskell

<lang JavaScript>(() => {

   'use strict';
   // NUMBERING CONSTRAINTS --------------------------------------------------
   // options :: Int -> Int -> Int -> [(Int, Int, Int)]
   const options = (lo, hi, total) => {
       const
           bind = flip(concatMap),
           ds = enumFromTo(lo, hi);
       return bind(filter(even, ds),
           x => bind(filter(d => d !== x, ds),
               y => bind([total - (x + y)],
                   z => (z !== y && lo <= z && z <= hi) ? [
                       [x, y, z]
                   ] : []
               )
           )
       )
   };
   // GENERIC FUNCTIONS ------------------------------------------------------
   // concatMap :: (a -> [b]) -> [a] -> [b]
   const concatMap = (f, xs) => [].concat.apply([], xs.map(f));
   // enumFromTo :: Int -> Int -> [Int]
   const enumFromTo = (m, n) =>
       Array.from({
           length: Math.floor(n - m) + 1
       }, (_, i) => m + i);
   // even :: Integral a => a -> Bool
   const even = n => n % 2 === 0;
   // filter :: (a -> Bool) -> [a] -> [a]
   const filter = (f, xs) => xs.filter(f);
   // flip :: (a -> b -> c) -> b -> a -> c
   const flip = f => (a, b) => f.apply(null, [b, a]);
   // length :: [a] -> Int
   const length = xs => xs.length;
   // map :: (a -> b) -> [a] -> [b]
   const map = (f, xs) => xs.map(f);
   // show :: a -> String
   const show = x => JSON.stringify(x) //, null, 2);
   // unlines :: [String] -> String
   const unlines = xs => xs.join('\n');
   // TEST -------------------------------------------------------------------
   const xs = options(1, 7, 12);
   return '(Police, Sanitation, Fire)\n\n' +
       unlines(map(show, xs)) +
       '\n\nNumber of options: ' + length(xs);

})();</lang>

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]

Number of options: 14

Kotlin

<lang scala>// version 1.1.2

fun main(args: Array<String>) {

   println("Police  Sanitation  Fire")
   println("------  ----------  ----")
   var count = 0
   for (i in 2..6 step 2) {
       for (j in 1..7) {
           if (j == i) continue
           for (k in 1..7) {
               if (k == i || k == j) continue
               if (i + j + k != 12) continue
               println("  $i         $j         $k")
               count++
           }
       }
   }
   println("\n$count valid combinations")

}</lang>

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

14 valid combinations

Lua

<lang lua> print( "Fire", "Police", "Sanitation" ) sol = 0 for f = 1, 7 do

   for p = 1, 7 do
       for s = 1, 7 do
           if s + p + f == 12 and p % 2 == 0 and f ~= p and f ~= s and p ~= s then
               print( f, p, s ); sol = sol + 1
           end
       end
   end

end print( string.format( "\n%d solutions found", sol ) ) </lang>

Output:
Fire    Police  Sanitation
1       4       7
1       6       5
2       4       6
2       6       4
3       2       7
3       4       5
4       2       6
4       6       2
5       4       3
5       6       1
6       2       4
6       4       2
7       2       3
7       4       1

14 solutions found

Perl

<lang Perl>

  1. !/usr/bin/perl

my @even_numbers;

for (1..7) {

 if ( $_ % 2 == 0)
 {
   push @even_numbers, $_;
 }

}

print "Police\tFire\tSanitation\n";

foreach my $police_number (@even_numbers) {

 for my $fire_number (1..7)
 {
   for my $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";
     }
   }
 }	

} </lang>

Perl 6

<lang perl6>for (1..7).combinations(3).grep(*.sum == 12) {

   for   .permutations\  .grep(*.[0] %%  2) {
       say <police fire sanitation> Z=> .list;
   }

} </lang>

Output:
(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)

REXX

bare bones

<lang rexx>/*REXX program finds/displays all possible variants of (3) department numbering puzzle.*/ say 'police fire sanitation' /*display a crude title for the output.*/

 do     p=2   to 7  by 2                        /*try numbers for the police department*/
   do   f=1  for 7                              /* "     "     "   "  fire        "    */
     do s=1  for 7;             $=p+f+s         /* "     "     "   "  sanitation  "    */
     if f\==p & s\==p & s\==f & $==12  then say  center(p,6)   center(f,5)   center(s,10)
     end   /*s*/
   end     /*f*/
 end       /*p*/                                /*stick a fork in it,  we're all done. */</lang>
output   when using the default inputs:
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

options and optimizing

A little extra code was added to allow the specification for the high department number as well as the sum.

Two optimizing statements were added (for speed),   but for this simple puzzle they aren't needed.

Also, extra code was added to nicely format a title (header) for the output, as well as displaying the number of solutions found. <lang rexx>/*REXX program finds/displays all possible variants of (3) department numbering puzzle.*/ parse arg high sum . /*obtain optional arguments from the CL*/ if high== | high=="," then high= 7 /*Not specified? Then use the default.*/ if sum== | sum=="," then sum=12 /* " " " " " " */ @pd= ' police '; @fd= " fire "  ; @sd= ' sanitation ' /*define names of departments.*/ @dept= ' department '; L=length(@dept) /*literal; and also its length*/

  1. =0 /*initialize the number of solutions. */
   do PD=2  by 2  to high                       /*try numbers for the police department*/
      do FD=1   for  high                       /* "     "     "   "  fire       "     */
      if FD==PD       then iterate              /*Same FD# & PD#?  They must be unique.*/
      if FD+PD>sum-1  then iterate PD           /*Is sum too large?   Try another PD#. */    /* ◄■■■■■■ optimizing code*/
         do SD=1  for  high                     /*try numbers for the sanitation dept. */
         if SD==PD | SD==FD  then iterate       /*Is SD# ¬unique?  They must be unique,*/
         $=PD+FD+SD                             /*compute sum of department numbers.   */
         if $>  sum   then iterate FD           /*Is the sum too high?  Try another FD#*/    /* ◄■■■■■■ optimizing code*/
         if $\==sum   then iterate              /*Is the sum ¬correct?   "     "    SD#*/
         #=# + 1                                /*bump the number of solutions (so far)*/
         if #==1 then do                        /*Is this the 1st solution?   Show hdr.*/
                      say center(@pd, L)      center(@fd, L)      center(@sd, L)
                      say copies(center(   @dept, L)' ', 3)
                      say copies(center('number', L)' ', 3)
                      say center(, L, "═")  center(, L, "═")  center(, L, "═")
                      end
         say  center(PD, L)   center(FD, L)   center(SD, L)       /*display a solution.*/
         end   /*SD*/
      end      /*FD*/
   end         /*PD*/

say /*display a blank line before the #sols*/ if #==0 then #= 'no' /*use a better word for bupkis. */ say # "solutions found." /*stick a fork in it, we're all done. */</lang>

output   when using the default inputs:
   police        fire      sanitation
 department   department   department
   number       number       number
════════════ ════════════ ════════════
     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.

Scala

<lang scala>val depts = {

 (1 to 7).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") ) } </lang>

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)

zkl

<lang zkl>Utils.Helpers.pickNFrom(3,[1..7].walk()) // 35 combos .filter(fcn(numbers){ numbers.sum(0)==12 }) // which all sum to 12 (==5) .println();</lang>

Output:
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 one solution: a=2,b=4

For a table with repeated solutions using nested loops: <lang zkl>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) }</lang>
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