Advertisement
steveoc64

city_slicker.zig

Nov 2nd, 2023 (edited)
51
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Python3 version - 600_000ns
  2. // Zig version -Doptimize=ReleaseFast = 60_000ns
  3. // Mac M2Pro
  4.  
  5. const std = @import("std");
  6.  
  7. const Country = struct {
  8.     name: []const u8,
  9.     population: f32,
  10.     isInEu: bool,
  11.     hasCoastline: bool,
  12.     pub fn format(this: Country, comptime _: []const u8, _: std.fmt.FormatOptions, stream: anytype) !void {
  13.         try stream.print(
  14.             "Country=`{[name]s}`, population={[population]d:.3}, isInEu={[isInEu]}, hasCoastline={[hasCoastline]}",
  15.             this,
  16.         );
  17.     }
  18. };
  19.  
  20. const City = struct {
  21.     name: []const u8,
  22.     country: ?*const Country,
  23.     latitude: f32,
  24.     longitude: f32,
  25.     temperature: f32,
  26.     pub fn format(this: City, comptime _: []const u8, _: std.fmt.FormatOptions, stream: anytype) !void {
  27.         try stream.print(
  28.             "CityName=`{[name]s}`, country={[country]?}, latitude={[latitude]d:.3}, longitude={[longitude]d:.3}, temperature={[temperature]d:.3}",
  29.             this,
  30.         );
  31.     }
  32. };
  33.  
  34. pub fn main() !void {
  35.     var timer = try std.time.Timer.start();
  36.  
  37.     var stdout_buffered = std.io.bufferedWriter(std.io.getStdOut().writer());
  38.     const stdout = stdout_buffered.writer();
  39.     defer {
  40.         stdout_buffered.flush() catch {};
  41.     }
  42.  
  43.     // const stdout = std.io.getStdOut().writer();
  44.     var GPA = std.heap.GeneralPurposeAllocator(.{}){};
  45.     defer _ = GPA.deinit();
  46.     const allocator = GPA.allocator();
  47.     const countriesData = @embedFile("Countries.csv");
  48.     var countries = std.StringHashMap(Country).init(allocator);
  49.     defer countries.deinit();
  50.     var countryIt = std.mem.splitScalar(u8, countriesData, '\n');
  51.     _ = countryIt.first(); //Ignore header
  52.     while (countryIt.next()) |originalCountryData| {
  53.         const countryData = std.mem.trimRight(u8, originalCountryData, "\n\r\t ");
  54.         var dataIt = std.mem.splitScalar(u8, countryData, ',');
  55.         const countryName = dataIt.first();
  56.         countries.put(countryName, Country{
  57.             .name = countryName,
  58.             .population = try std.fmt.parseFloat(f32, dataIt.next() orelse {
  59.                 return stdout.print("{s}{s}{s}", .{ "Failed to parse population for country `", countryName, "`.\n" });
  60.             }),
  61.             .isInEu = !std.mem.eql(u8, dataIt.next() orelse {
  62.                 return stdout.print("{s}{s}{s}", .{ "Failed to parse isInEu for country `", countryName, "`.\n" });
  63.             }, "no"),
  64.             .hasCoastline = !std.mem.eql(u8, dataIt.next() orelse {
  65.                 return stdout.print("{s}{s}{s}", .{ "Failed to parse hasCoastline for country `", countryName, "`.\n" });
  66.             }, "no"),
  67.         }) catch {
  68.             return stdout.print("{s}{s}{s}", .{ "Failed to allocate memory for country `", countryName, "`.\n" });
  69.         };
  70.     }
  71.     const citiesData = @embedFile("Cities.csv");
  72.     var cities = try std.ArrayList(City).initCapacity(allocator, std.mem.count(u8, citiesData, "\n"));
  73.     //var cities = std.ArrayList(City).init(allocator);
  74.     defer cities.deinit();
  75.     var cityIt = std.mem.splitScalar(u8, citiesData, '\n');
  76.     _ = cityIt.first(); //Ignore header
  77.     while (cityIt.next()) |originalcityData| {
  78.         const cityData = std.mem.trimRight(u8, originalcityData, "\n\r\t ");
  79.         var dataIt = std.mem.splitScalar(u8, cityData, ',');
  80.         const cityName = dataIt.first();
  81.         const new_city = try cities.addOne();
  82.         new_city.* = .{
  83.             .name = cityName,
  84.             .country = countries.getPtr(dataIt.next() orelse {
  85.                 return stdout.print("{s}{s}{s}", .{ "Failed to parse country for city `", cityName, "`.\n" });
  86.             }),
  87.             .latitude = try std.fmt.parseFloat(f32, dataIt.next() orelse {
  88.                 return stdout.print("{s}{s}{s}", .{ "Expecting latitude city `", cityName, "`.\n" });
  89.             }),
  90.             .longitude = try std.fmt.parseFloat(f32, dataIt.next() orelse {
  91.                 return stdout.print("{s}{s}{s}", .{ "Expecting longitude for city `", cityName, "`.\n" });
  92.             }),
  93.             .temperature = try std.fmt.parseFloat(f32, dataIt.next() orelse {
  94.                 return stdout.print("{s}{s}{s}", .{ "Expecting temperature for city `", cityName, "`.\n" });
  95.             }),
  96.         };
  97.     }
  98.     try stdout.writeAll("All cities that are not in the EU and whose average temperatures are below 5.0:\n");
  99.     for (cities.items) |city| {
  100.         if (city.temperature < 5 and !(city.country orelse continue).isInEu)
  101.             try stdout.print("{any}{c}", .{ city, '\n' });
  102.     }
  103.     try stdout.writeAll("Average temperature for all cities in Italy:\n");
  104.     const avgItalyTemp = blk: {
  105.         var count: usize = 0;
  106.         var totalTemp: f32 = 0;
  107.         for (cities.items) |city| {
  108.             if (city.country) |cc| {
  109.                 if (std.mem.eql(u8, cc.name, "Italy")) {
  110.                     count += 1;
  111.                     totalTemp += city.temperature;
  112.                 }
  113.             }
  114.         }
  115.         break :blk totalTemp / @as(f32, @floatFromInt(count));
  116.     };
  117.     try stdout.print("{d:.5}{c}", .{ avgItalyTemp, '\n' });
  118.     const timeElapsed = timer.read();
  119.     try stdout.print("{s}{d}{s}", .{ "Time elapsed: ", timeElapsed, " nanoseconds\n" });
  120. }
  121.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement