DEV Community

dev.to staff
dev.to staff

Posted on

3

Daily Challenge #216 - Rainfall

data and data1 are two strings with rainfall records of a few cities for months from January to December. The records of towns are separated by \n. The name of each town is followed by :.

const data = 
     "Rome:Jan 81.2,Feb 63.2,Mar 70.3,Apr 55.7,May 53.0,Jun 36.4,Jul 17.5,Aug 27.5,Sep 60.9,Oct 117.7,Nov 111.0,Dec 97.9" + "\n" +
     "London:Jan 48.0,Feb 38.9,Mar 39.9,Apr 42.2,May 47.3,Jun 52.1,Jul 59.5,Aug 57.2,Sep 55.4,Oct 62.0,Nov 59.0,Dec 52.9" + "\n" +
     "Paris:Jan 182.3,Feb 120.6,Mar 158.1,Apr 204.9,May 323.1,Jun 300.5,Jul 236.8,Aug 192.9,Sep 66.3,Oct 63.3,Nov 83.2,Dec 154.7" + "\n" +
     "NY:Jan 108.7,Feb 101.8,Mar 131.9,Apr 93.5,May 98.8,Jun 93.6,Jul 102.2,Aug 131.8,Sep 92.0,Oct 82.3,Nov 107.8,Dec 94.2" + "\n" +
     "Vancouver:Jan 145.7,Feb 121.4,Mar 102.3,Apr 69.2,May 55.8,Jun 47.1,Jul 31.3,Aug 37.0,Sep 59.6,Oct 116.3,Nov 154.6,Dec 171.5" + "\n" +
     "Sydney:Jan 103.4,Feb 111.0,Mar 131.3,Apr 129.7,May 123.0,Jun 129.2,Jul 102.8,Aug 80.3,Sep 69.3,Oct 82.6,Nov 81.4,Dec 78.2" + "\n" +
     "Bangkok:Jan 10.6,Feb 28.2,Mar 30.7,Apr 71.8,May 189.4,Jun 151.7,Jul 158.2,Aug 187.0,Sep 319.9,Oct 230.8,Nov 57.3,Dec 9.4" + "\n" +
     "Tokyo:Jan 49.9,Feb 71.5,Mar 106.4,Apr 129.2,May 144.0,Jun 176.0,Jul 135.6,Aug 148.5,Sep 216.4,Oct 194.1,Nov 95.6,Dec 54.4" + "\n" +
     "Beijing:Jan 3.9,Feb 4.7,Mar 8.2,Apr 18.4,May 33.0,Jun 78.1,Jul 224.3,Aug 170.0,Sep 58.4,Oct 18.0,Nov 9.3,Dec 2.7" + "\n" +
     "Lima:Jan 1.2,Feb 0.9,Mar 0.7,Apr 0.4,May 0.6,Jun 1.8,Jul 4.4,Aug 3.1,Sep 3.3,Oct 1.7,Nov 0.5,Dec 0.7";
const data1 =
     "Rome:Jan 90.2,Feb 73.2,Mar 80.3,Apr 55.7,May 53.0,Jun 36.4,Jul 17.5,Aug 27.5,Sep 60.9,Oct 147.7,Nov 121.0,Dec 97.9" + "\n" +
     "London:Jan 58.0,Feb 38.9,Mar 49.9,Apr 42.2,May 67.3,Jun 52.1,Jul 59.5,Aug 77.2,Sep 55.4,Oct 62.0,Nov 69.0,Dec 52.9" + "\n" +
     "Paris:Jan 182.3,Feb 120.6,Mar 188.1,Apr 204.9,May 323.1,Jun 350.5,Jul 336.8,Aug 192.9,Sep 66.3,Oct 63.3,Nov 83.2,Dec 154.7" + "\n" +
     "NY:Jan 128.7,Feb 121.8,Mar 151.9,Apr 93.5,May 98.8,Jun 93.6,Jul 142.2,Aug 131.8,Sep 92.0,Oct 82.3,Nov 107.8,Dec 94.2" + "\n" +
     "Vancouver:Jan 155.7,Feb 121.4,Mar 132.3,Apr 69.2,May 85.8,Jun 47.1,Jul 31.3,Aug 37.0,Sep 69.6,Oct 116.3,Nov 154.6,Dec 171.5" + "\n" +
     "Sydney:Jan 123.4,Feb 111.0,Mar 151.3,Apr 129.7,May 123.0,Jun 159.2,Jul 102.8,Aug 90.3,Sep 69.3,Oct 82.6,Nov 81.4,Dec 78.2" + "\n" +
     "Bangkok:Jan 20.6,Feb 28.2,Mar 40.7,Apr 81.8,May 189.4,Jun 151.7,Jul 198.2,Aug 197.0,Sep 319.9,Oct 230.8,Nov 57.3,Dec 9.4" + "\n" +
     "Tokyo:Jan 59.9,Feb 81.5,Mar 106.4,Apr 139.2,May 144.0,Jun 186.0,Jul 155.6,Aug 148.5,Sep 216.4,Oct 194.1,Nov 95.6,Dec 54.4" + "\n" +
     "Beijing:Jan 13.9,Feb 14.7,Mar 18.2,Apr 18.4,May 43.0,Jun 88.1,Jul 224.3,Aug 170.0,Sep 58.4,Oct 38.0,Nov 19.3,Dec 2.7" + "\n" +
     "Lima:Jan 11.2,Feb 10.9,Mar 10.7,Apr 10.4,May 10.6,Jun 11.8,Jul 14.4,Aug 13.1,Sep 23.3,Oct 1.7,Nov 0.5,Dec 10.7";
const towns = ["Rome", "London", "Paris", "NY", "Vancouver", "Sydney", "Bangkok", "Tokyo",
               "Beijing", "Lima", "Montevideo", "Caracas", "Madrid", "Berlin"]

function: mean(town, string) should return the average of rainfall for the city town and the string data or data1.

function: variance(town, string) should return the variance of rainfall for the city town and the string data or data1.

If functions mean or variance have as parameter town a city which has no records, return -1.

A reference to help: http://www.mathsisfun.com/data/standard-deviation.html
data and data1 (can be named d0 and d1 depending on the language) are adapted from: http://www.worldclimate.com

Examples

mean("London", data) => 51.19(9999999999996)
variance("London", data) => 57.42(833333333374)

Tests

mean(Rome, data1);
mean(Beijing, data);

variance(Beijing, data1);
variance(Lima, data);

Good luck!


This challenge comes from g964 on CodeWars. Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge idea for a future post? Email yo+challenge@dev.to with your suggestions!

AWS Q Developer image

Your AI Code Assistant

Generate and update README files, create data-flow diagrams, and keep your project fully documented. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

Top comments (11)

Collapse
 
vidit1999 profile image
Vidit Sarkar

Python solution

# load the data in a dictionary
# dict keys are towns
# and value is another dict with keys 'mean' and 'variancne'
# and values with mean and variance of the respective towns
# Example:
# to_dict_load(data) ->
# {'Rome': {'mean': 66.02499999999999, 'variance': 915.3852083333335},
# 'London': {'mean': 51.199999999999996, 'variance': 57.428333333333335} ... }
def to_dict_load(data):
    all_towns = data.split("\n")
    town_wise = {}
    for i in range(len(all_towns)):
        town_name, values = all_towns[i].split(":")
        values = values.split(",")
        vals = [float(v.split(" ")[1]) for v in values]
        mean = sum(vals)/len(vals)
        variance= sum(map(lambda x : (x-mean)*(x-mean), vals))/len(vals)
        town_wise[town_name] = {'mean': mean, 'variance': variance}
    return town_wise

# returns mean of rainfall in a town according to data
def mean(town, data):
    dt = to_dict_load(data)
    if town in dt:
        return dt[town]['mean']
    return -1

# returns variance of rainfall in a town according to data
def variance(town, data):
    dt = to_dict_load(data)
    if town in dt:
        return dt[town]['variance']
    return -1
Collapse
 
mellen profile image
Matt Ellen-Tsivintzeli • Edited

Javascript with regex

function getData(rfd)
{
  let lines = rfd.split('\n');
  let cmap = new Map(lines.map(l => 
                               {
                                 let parts = l.split(':');
                                 return [parts[0], parts[1].split(/[^0-9.]+/)
                                                           .filter(v => v.length > 0)
                                                           .map(v => parseFloat(v))]
                               }));
  return cmap;  
}

function mean(country, rainfalldata)
{
  let d = getData(rainfalldata).get(country);
  if(!d)
  {
    return -1;
  }
  return d.reduce((acc, v) => acc + v, 0) / d.length;
}

function variance(country, rainfalldata)
{
  let m = mean(country, rainfalldata);
  if(m === -1)
  {
    return -1;
  }
  let d = getData(rainfalldata).get(country);
  return d.map(v => (v - m) * (v - m)).reduce((acc, v) => acc + v, 0) / (d.length)
}
Collapse
 
differentmatt profile image
Matt Lott

Fyi, you can add language specific syntax styling immediately after the first code back-ticks.

github.com/adam-p/markdown-here/wi...

Collapse
 
mellen profile image
Matt Ellen-Tsivintzeli

Ah! I hadn't closed the three back ticks!

Collapse
 
mellen profile image
Matt Ellen-Tsivintzeli

Thanks, Matt. I tried that, and if you see my other posts you'll see I was successful, but it's not working for this one for some reason

Collapse
 
differentmatt profile image
Matt Lott

JS solution

const parseData = (string) => {
  // Return map of cities and their rainfalls, assumes well-formed data
  return string.split('\n').map(line => line.split(':'))
    .map(cityMonths => {
      return {
        city: cityMonths[0],
        rainfalls: cityMonths[1].split(',')
          .map(month => parseFloat(month.split(' ')[1]))
          .filter(r => !isNaN(r))
      }
    })
    .reduce((m, cityRainfalls) => {
      m[cityRainfalls.city] = cityRainfalls.rainfalls
      return m
    }, {})
}

const calcMean = (nums) => nums.reduce((t, n) => t + n, 0) / nums.length

const calcVariance = (nums) => {
  const mean = calcMean(nums)
  return calcMean(nums.map(num => Math.pow(num - mean, 2)))
}

const mean = (town, string) => {
  const cityRainfallsMap = parseData(string)
  if (!cityRainfallsMap[town] || cityRainfallsMap[town].length < 1) return -1
  return calcMean(cityRainfallsMap[town])
}

const variance = (town, string) => {
  const cityRainfallsMap = parseData(string)
  if (!cityRainfallsMap[town] || cityRainfallsMap[town].length < 1) return -1
  return calcVariance(cityRainfallsMap[town])
}


// Tests assume data, data1 in scope

const test = (fn, town, string, expected) => {
  const result = fn(town, string)
  console.log(`${town} ${result} === ${expected} ?`)
}

test(variance, "London", data, 57.42833333333374)
test(mean, "London", data, 51.199999999999996)

test(mean, "Seattle", data, -1)
test(variance, "Seattle", data, -1)

test(mean, "Seattle", "Seattle:", -1)
test(variance, "Seattle", "Seattle:", -1)

test(variance, 'Beijing', data1, '4437.0380555556')
test(variance, 'Lima', data, '1.5790972222222')
Collapse
 
kesprit profile image
kesprit

My Swift solution, not the best ☹️:

func fetchCity(datas: String) -> [String: [Double]] {
    func fetchCityDatas(datas: String) -> [Double] {
        datas.split(separator: ",").map {
            Double($0.split(separator: .init(" ")).last ?? "") ?? 0
        }
    }

    return data.split(separator: "\n").reduce(into: [String:[Double]]()) {
        let data = $1.split(separator: ":")
        $0[String(data.first ?? "")] = fetchCityDatas(datas: String(data.last ?? ""))
    }
}

func mean(town: String, datas: String) -> Double {
    let convertedDatas = fetchCity(datas: datas)
    guard convertedDatas.contains(where: { $0.key == town }), let townDatas = convertedDatas[town] else { return -1 }

    let sum = townDatas.reduce(into: 0.0) { $0 += $1 }

    return sum / Double(townDatas.count)
}

func variance(town: String, datas: String) -> Double {
    let meanValue = mean(town: town, datas: datas)
    let convertedCities = fetchCity(datas: datas)
    guard let convertedDatas = convertedCities[town] else { return 0 }

    return convertedDatas.map { pow((meanValue - $0),2) }
        .reduce(into: 0.0) { $0 += $1 } / Double(convertedDatas.count)
}

mean(town: "Rome",datas: data1)
mean(town: "Beijing",datas: data)
variance(town: "Beijing",datas: data1)
variance(town: "Lima",datas: data)
Collapse
 
empereol profile image
Empereol

TypeScript

/**
 * Math Utilities
 */
interface Math {
  mean(...values: number[]): number;
  variance(...values: number[]): number;
}

Math.mean = (...values: number[]): number => values.reduce((t, v) => (t += v), 0) / values.length;

Math.variance = (...values: number[]): number => {
  const mean = Math.mean(...values);
  return Math.mean(...values.map(v => (v - mean) ** 2));
};

/**
 * Rainfall
 */
interface RainData {
  town: string;
  values: number[];
}

function createRainData(data: string): RainData[] {
  return data.split(/\n/).map(line => ({
    town: line.split(':')[0].trim(),
    values: line.match(/\d+\.\d+/gi).map(Number)
  }));
}

function getRainfall(town: string, data: string): number[] {
  const rainData = createRainData(data).find(d => d.town === town);
  return rainData ? rainData.values : [-1];
}

function mean(town: string, data: string): number {
  return Math.mean(...getRainfall(town, data));
}

function variance(town: string, data: string): number {
  return Math.variance(...getRainfall(town, data));
}
Collapse
 
aminnairi profile image
Amin • Edited
data : String
data =
    "Rome:Jan 81.2,Feb 63.2,Mar 70.3,Apr 55.7,May 53.0,Jun 36.4,Jul 17.5,Aug 27.5,Sep 60.9,Oct 117.7,Nov 111.0,Dec 97.9"
        ++ "\n"
        ++ "London:Jan 48.0,Feb 38.9,Mar 39.9,Apr 42.2,May 47.3,Jun 52.1,Jul 59.5,Aug 57.2,Sep 55.4,Oct 62.0,Nov 59.0,Dec 52.9"
        ++ "\n"
        ++ "Paris:Jan 182.3,Feb 120.6,Mar 158.1,Apr 204.9,May 323.1,Jun 300.5,Jul 236.8,Aug 192.9,Sep 66.3,Oct 63.3,Nov 83.2,Dec 154.7"
        ++ "\n"
        ++ "NY:Jan 108.7,Feb 101.8,Mar 131.9,Apr 93.5,May 98.8,Jun 93.6,Jul 102.2,Aug 131.8,Sep 92.0,Oct 82.3,Nov 107.8,Dec 94.2"
        ++ "\n"
        ++ "Vancouver:Jan 145.7,Feb 121.4,Mar 102.3,Apr 69.2,May 55.8,Jun 47.1,Jul 31.3,Aug 37.0,Sep 59.6,Oct 116.3,Nov 154.6,Dec 171.5"
        ++ "\n"
        ++ "Sydney:Jan 103.4,Feb 111.0,Mar 131.3,Apr 129.7,May 123.0,Jun 129.2,Jul 102.8,Aug 80.3,Sep 69.3,Oct 82.6,Nov 81.4,Dec 78.2"
        ++ "\n"
        ++ "Bangkok:Jan 10.6,Feb 28.2,Mar 30.7,Apr 71.8,May 189.4,Jun 151.7,Jul 158.2,Aug 187.0,Sep 319.9,Oct 230.8,Nov 57.3,Dec 9.4"
        ++ "\n"
        ++ "Tokyo:Jan 49.9,Feb 71.5,Mar 106.4,Apr 129.2,May 144.0,Jun 176.0,Jul 135.6,Aug 148.5,Sep 216.4,Oct 194.1,Nov 95.6,Dec 54.4"
        ++ "\n"
        ++ "Beijing:Jan 3.9,Feb 4.7,Mar 8.2,Apr 18.4,May 33.0,Jun 78.1,Jul 224.3,Aug 170.0,Sep 58.4,Oct 18.0,Nov 9.3,Dec 2.7"
        ++ "\n"
        ++ "Lima:Jan 1.2,Feb 0.9,Mar 0.7,Apr 0.4,May 0.6,Jun 1.8,Jul 4.4,Aug 3.1,Sep 3.3,Oct 1.7,Nov 0.5,Dec 0.7"
data1 : String
data1 =
    "Rome:Jan 90.2,Feb 73.2,Mar 80.3,Apr 55.7,May 53.0,Jun 36.4,Jul 17.5,Aug 27.5,Sep 60.9,Oct 147.7,Nov 121.0,Dec 97.9"
        ++ "\n"
        ++ "London:Jan 58.0,Feb 38.9,Mar 49.9,Apr 42.2,May 67.3,Jun 52.1,Jul 59.5,Aug 77.2,Sep 55.4,Oct 62.0,Nov 69.0,Dec 52.9"
        ++ "\n"
        ++ "Paris:Jan 182.3,Feb 120.6,Mar 188.1,Apr 204.9,May 323.1,Jun 350.5,Jul 336.8,Aug 192.9,Sep 66.3,Oct 63.3,Nov 83.2,Dec 154.7"
        ++ "\n"
        ++ "NY:Jan 128.7,Feb 121.8,Mar 151.9,Apr 93.5,May 98.8,Jun 93.6,Jul 142.2,Aug 131.8,Sep 92.0,Oct 82.3,Nov 107.8,Dec 94.2"
        ++ "\n"
        ++ "Vancouver:Jan 155.7,Feb 121.4,Mar 132.3,Apr 69.2,May 85.8,Jun 47.1,Jul 31.3,Aug 37.0,Sep 69.6,Oct 116.3,Nov 154.6,Dec 171.5"
        ++ "\n"
        ++ "Sydney:Jan 123.4,Feb 111.0,Mar 151.3,Apr 129.7,May 123.0,Jun 159.2,Jul 102.8,Aug 90.3,Sep 69.3,Oct 82.6,Nov 81.4,Dec 78.2"
        ++ "\n"
        ++ "Bangkok:Jan 20.6,Feb 28.2,Mar 40.7,Apr 81.8,May 189.4,Jun 151.7,Jul 198.2,Aug 197.0,Sep 319.9,Oct 230.8,Nov 57.3,Dec 9.4"
        ++ "\n"
        ++ "Tokyo:Jan 59.9,Feb 81.5,Mar 106.4,Apr 139.2,May 144.0,Jun 186.0,Jul 155.6,Aug 148.5,Sep 216.4,Oct 194.1,Nov 95.6,Dec 54.4"
        ++ "\n"
        ++ "Beijing:Jan 13.9,Feb 14.7,Mar 18.2,Apr 18.4,May 43.0,Jun 88.1,Jul 224.3,Aug 170.0,Sep 58.4,Oct 38.0,Nov 19.3,Dec 2.7"
        ++ "\n"
        ++ "Lima:Jan 11.2,Feb 10.9,Mar 10.7,Apr 10.4,May 10.6,Jun 11.8,Jul 14.4,Aug 13.1,Sep 23.3,Oct 1.7,Nov 0.5,Dec 10.7"
Collapse
 
mushtaqasif profile image
mushtaqasif • Edited

JS Solution

const [mean, variance] = (() => {
    const calc = (town, data, type = false) => {
        return data.split('\n').reduce((result, row) => {
            let [city, rainfallData] = row.split(':');

            if (city != town) return result;

            let rainfallMonthlyData = rainfallData.split(',');

            let rainfallAmounts = [];

            let mean = rainfallMonthlyData.reduce((total, record) => {
                let rainfallAmount = parseFloat(record.split(' ')[1]);

                rainfallAmounts.push(rainfallAmount);

                return total + rainfallAmount;
            }, 0) / rainfallMonthlyData.length; 

            return !type ? mean : rainfallAmounts.reduce((total, rainfallAmount) => 
                total + Math.pow((rainfallAmount - mean), 2)
            , 0) / rainfallMonthlyData.length; 
        }, -1);
    };

    return [
        (town, data) => calc(town, data),
        (town, data) => calc(town, data, true)
    ];
})();

console.log(JSON.stringify({
    London: {
        mean: mean("London", data),
        variance: variance("London", data)
    },
    mean: {
        Rome: mean('Rome', data1),
        Beijing: mean('Beijing', data)
    },
    variance: {
        Beijing: variance('Beijing', data1),
        Lima: variance('Lima', data)
    }
}, undefined, 4));

output:

{
    "London": {
        "mean": 51.199999999999996,
        "variance": 57.428333333333335
    },
    "mean": {
        "Rome": 71.77499999999999,
        "Beijing": 52.416666666666664
    },
    "variance": {
        "Beijing": 4437.038055555556,
        "Lima": 1.5790972222222222
    }
}
Collapse
 
cipharius profile image
Valts Liepiņš

Solution in Haskell:

import Data.List (find)

calcMean :: [Double] -> Double
calcMean [] = -1
calcMean xs = (foldr (+) 0 xs) / (fromIntegral . length $ xs)

calcVar :: [Double] -> Double
calcVar [] = -1
calcVar xs = calcMean . fmap diff $ xs
  where diff x = (x - calcMean xs)^2

getValues :: String -> String -> [Double]
getValues town = maybe [] parse . find theTown . lines
  where
    theTown = (==town) . takeWhile (/=':')
    parse = fmap (read . takeWhile (/=',')) . tail . words

mean :: String -> String -> Double
mean town = calcMean . getValues town

variance :: String -> String -> Double
variance town = calcVar . getValues town

Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

Rather than just generating snippets, our agents understand your entire project context, can make decisions, use tools, and carry out tasks autonomously.

Read full post

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay