github.com/vpayno/adventofcode-2022-golang-workspace@v0.0.0-20230605190011-dbafed5593de/reports/coverage.html (about) 1 2 <!DOCTYPE html> 3 <html> 4 <head> 5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 6 <title>day01: Go Coverage Report</title> 7 <style> 8 body { 9 background: black; 10 color: rgb(80, 80, 80); 11 } 12 body, pre, #legend span { 13 font-family: Menlo, monospace; 14 font-weight: bold; 15 } 16 #topbar { 17 background: black; 18 position: fixed; 19 top: 0; left: 0; right: 0; 20 height: 42px; 21 border-bottom: 1px solid rgb(80, 80, 80); 22 } 23 #content { 24 margin-top: 50px; 25 } 26 #nav, #legend { 27 float: left; 28 margin-left: 10px; 29 } 30 #legend { 31 margin-top: 12px; 32 } 33 #nav { 34 margin-top: 10px; 35 } 36 #legend span { 37 margin: 0 5px; 38 } 39 .cov0 { color: rgb(192, 0, 0) } 40 .cov1 { color: rgb(128, 128, 128) } 41 .cov2 { color: rgb(116, 140, 131) } 42 .cov3 { color: rgb(104, 152, 134) } 43 .cov4 { color: rgb(92, 164, 137) } 44 .cov5 { color: rgb(80, 176, 140) } 45 .cov6 { color: rgb(68, 188, 143) } 46 .cov7 { color: rgb(56, 200, 146) } 47 .cov8 { color: rgb(44, 212, 149) } 48 .cov9 { color: rgb(32, 224, 152) } 49 .cov10 { color: rgb(20, 236, 155) } 50 51 </style> 52 </head> 53 <body> 54 <div id="topbar"> 55 <div id="nav"> 56 <select id="files"> 57 58 <option value="file0">github.com/vpayno/adventofcode-2022-golang-workspace/cmd/day01/aoc-day01.go (100.0%)</option> 59 60 <option value="file1">github.com/vpayno/adventofcode-2022-golang-workspace/cmd/day02/aoc-day02.go (100.0%)</option> 61 62 <option value="file2">github.com/vpayno/adventofcode-2022-golang-workspace/cmd/day03/aoc-day03.go (100.0%)</option> 63 64 <option value="file3">github.com/vpayno/adventofcode-2022-golang-workspace/cmd/day04/aoc-day04.go (100.0%)</option> 65 66 <option value="file4">github.com/vpayno/adventofcode-2022-golang-workspace/internal/aocshared/aocshared.go (100.0%)</option> 67 68 <option value="file5">github.com/vpayno/adventofcode-2022-golang-workspace/internal/day01/app.go (100.0%)</option> 69 70 <option value="file6">github.com/vpayno/adventofcode-2022-golang-workspace/internal/day01/init.go (100.0%)</option> 71 72 <option value="file7">github.com/vpayno/adventofcode-2022-golang-workspace/internal/day02/app.go (100.0%)</option> 73 74 <option value="file8">github.com/vpayno/adventofcode-2022-golang-workspace/internal/day02/init.go (100.0%)</option> 75 76 <option value="file9">github.com/vpayno/adventofcode-2022-golang-workspace/internal/day03/app.go (100.0%)</option> 77 78 <option value="file10">github.com/vpayno/adventofcode-2022-golang-workspace/internal/day03/init.go (100.0%)</option> 79 80 <option value="file11">github.com/vpayno/adventofcode-2022-golang-workspace/internal/day04/app.go (100.0%)</option> 81 82 <option value="file12">github.com/vpayno/adventofcode-2022-golang-workspace/internal/day04/init.go (100.0%)</option> 83 84 </select> 85 </div> 86 <div id="legend"> 87 <span>not tracked</span> 88 89 <span class="cov0">no coverage</span> 90 <span class="cov1">low coverage</span> 91 <span class="cov2">*</span> 92 <span class="cov3">*</span> 93 <span class="cov4">*</span> 94 <span class="cov5">*</span> 95 <span class="cov6">*</span> 96 <span class="cov7">*</span> 97 <span class="cov8">*</span> 98 <span class="cov9">*</span> 99 <span class="cov10">high coverage</span> 100 101 </div> 102 </div> 103 <div id="content"> 104 105 <pre class="file" id="file0" style="display: none">// Package main is the cli module for the application. 106 package main 107 108 import ( 109 "fmt" 110 111 app "github.com/vpayno/adventofcode-2022-golang-workspace/internal/day01" 112 ) 113 114 var challengeName = "day01" 115 116 func main() <span class="cov10" title="2">{ 117 // Create the configuration object. 118 conf := app.Setup(challengeName) 119 120 // Run the main application. 121 err := app.Run(conf) 122 if err != nil </span><span class="cov1" title="1">{ 123 fmt.Println("Encountered error while running app.Run()") 124 fmt.Println() 125 fmt.Println(err) 126 127 // Don't panic 128 return 129 }</span> 130 } 131 </pre> 132 133 <pre class="file" id="file1" style="display: none">// Package main is the cli module for the application. 134 package main 135 136 import ( 137 "fmt" 138 139 app "github.com/vpayno/adventofcode-2022-golang-workspace/internal/day02" 140 ) 141 142 var challengeName = "day02" 143 144 func main() <span class="cov10" title="2">{ 145 // Create the configuration object. 146 conf := app.Setup(challengeName) 147 148 // Run the main application. 149 err := app.Run(conf) 150 if err != nil </span><span class="cov1" title="1">{ 151 fmt.Println("Encountered error while running app.Run()") 152 fmt.Println() 153 fmt.Println(err) 154 155 // Don't panic 156 return 157 }</span> 158 } 159 </pre> 160 161 <pre class="file" id="file2" style="display: none">// Package main is the cli module for the application. 162 package main 163 164 import ( 165 "fmt" 166 167 app "github.com/vpayno/adventofcode-2022-golang-workspace/internal/day03" 168 ) 169 170 var challengeName = "day03" 171 172 func main() <span class="cov10" title="2">{ 173 // Create the configuration object. 174 conf := app.Setup(challengeName) 175 176 // Run the main application. 177 err := app.Run(conf) 178 if err != nil </span><span class="cov1" title="1">{ 179 fmt.Println("Encountered error while running app.Run()") 180 fmt.Println() 181 fmt.Println(err) 182 183 // Don't panic 184 return 185 }</span> 186 } 187 </pre> 188 189 <pre class="file" id="file3" style="display: none">// Package main is the cli module for the application. 190 package main 191 192 import ( 193 "fmt" 194 195 app "github.com/vpayno/adventofcode-2022-golang-workspace/internal/day04" 196 ) 197 198 var challengeName = "day04" 199 200 func main() <span class="cov10" title="2">{ 201 // Create the configuration object. 202 conf := app.Setup(challengeName) 203 204 // Run the main application. 205 err := app.Run(conf) 206 if err != nil </span><span class="cov1" title="1">{ 207 fmt.Println("Encountered error while running app.Run()") 208 fmt.Println() 209 fmt.Println(err) 210 211 // Don't panic 212 return 213 }</span> 214 } 215 </pre> 216 217 <pre class="file" id="file4" style="display: none">// Package aocshared is the module with the cli logic for the application. 218 package aocshared 219 220 import ( 221 "bufio" 222 "fmt" 223 "os" 224 "path/filepath" 225 ) 226 227 // GetFile takes a file name and returns a file handle. 228 func GetFile(fileName string) (*os.File, error) <span class="cov7" title="4">{ 229 fileRoot, err := os.Getwd() 230 if err != nil </span><span class="cov1" title="1">{ 231 return nil, err 232 }</span> 233 234 <span class="cov6" title="3">fileRoot = filepath.Clean(fileRoot + "/../../") 235 fileName = filepath.Clean(fileRoot + "/" + fileName) 236 237 // strings.HasPrefix() is pointless since we're generating the full path. 238 239 // https://securego.io/docs/rules/g304.html - this gosec check seems to want 240 // panic() calls 241 file, err := os.Open(fileName) // #nosec 242 243 return file, err</span> 244 } 245 246 // GetScanner takes a file handle and returns a bufio scanner. 247 func GetScanner(file *os.File) *bufio.Scanner <span class="cov1" title="1">{ 248 scanner := bufio.NewScanner(file) 249 scanner.Split(bufio.ScanLines) 250 251 return scanner 252 }</span> 253 254 // ShowResult prints the passed integer. 255 func ShowResult(result int) <span class="cov1" title="1">{ 256 fmt.Printf("%d\n", result) 257 }</span> 258 259 // Empty type to avoid ugly struct{}{} 260 var Empty struct{} 261 262 // Set holds a collection of unique items. 263 type Set map[rune]struct{} 264 265 // SetFromSlice creates a set from a slice. 266 func SetFromSlice(slice []rune) Set <span class="cov1" title="1">{ 267 set := make(Set) 268 269 for _, element := range slice </span><span class="cov10" title="6">{ 270 set[element] = Empty 271 }</span> 272 273 <span class="cov1" title="1">return set</span> 274 } 275 276 // SetIntersect finds the intersection of two sets. 277 func SetIntersect(s1, s2 Set) []rune <span class="cov1" title="1">{ 278 common := []rune{} 279 280 for key := range s1 </span><span class="cov7" title="4">{ 281 _, found := s2[key] 282 if found </span><span class="cov1" title="1">{ 283 common = append(common, key) 284 }</span> 285 } 286 287 <span class="cov1" title="1">return common</span> 288 } 289 290 // SplitString converts a string into a slice of runes. 291 func SplitString(str string) []rune <span class="cov1" title="1">{ 292 runes := []rune{} 293 294 for _, r := range str </span><span class="cov7" title="4">{ 295 runes = append(runes, r) 296 }</span> 297 298 <span class="cov1" title="1">return runes</span> 299 } 300 </pre> 301 302 <pre class="file" id="file5" style="display: none">// Package day01 is the module with the cli logic for the application. 303 package day01 304 305 import ( 306 "bufio" 307 "fmt" 308 "sort" 309 "strconv" 310 311 "github.com/vpayno/adventofcode-2022-golang-workspace/internal/aocshared" 312 ) 313 314 // Run is called my the gain function. It's basically the main function of the app. 315 func Run(conf Config) error <span class="cov2" title="3">{ 316 file, err := aocshared.GetFile(conf.inputFileName) 317 if err != nil </span><span class="cov1" title="1">{ 318 return err 319 }</span> 320 321 <span class="cov1" title="2">scanner := aocshared.GetScanner(file) 322 323 data, err := loadData(scanner) 324 if err != nil </span><span class="cov1" title="1">{ 325 return err 326 }</span> 327 328 <span class="cov1" title="1">topCalories := getMaxCalories(data) 329 330 aocshared.ShowResult(topCalories) 331 332 topThreeCalories := getResultTopThreeCalories(data) 333 334 aocshared.ShowResult(topThreeCalories) 335 336 return nil</span> 337 } 338 339 func loadData(file *bufio.Scanner) (map[string]int, error) <span class="cov2" title="4">{ 340 var err error 341 342 data := map[string]int{} 343 344 var elfCounter = 1 345 var calories int 346 347 for file.Scan() </span><span class="cov10" title="4482">{ 348 line := file.Text() 349 350 elfName := fmt.Sprintf("%s%d", "elf", elfCounter) 351 352 if line == "" </span><span class="cov7" title="482">{ 353 elfCounter++ 354 data[elfName] = calories 355 calories = 0 356 357 continue</span> 358 } 359 360 <span class="cov9" title="4000">calorie, err := strconv.Atoi(line) 361 if err != nil </span><span class="cov1" title="2">{ 362 return map[string]int{}, err 363 }</span> 364 365 <span class="cov9" title="3998">calories += calorie</span> 366 } 367 368 <span class="cov1" title="2">return data, err</span> 369 } 370 371 func getMaxCalories(data map[string]int) int <span class="cov1" title="2">{ 372 var result int 373 374 for _, calories := range data </span><span class="cov6" title="246">{ 375 if calories > result </span><span class="cov3" title="8">{ 376 result = calories 377 }</span> 378 } 379 380 <span class="cov1" title="2">return result</span> 381 } 382 383 func getTopThreeSum(calories []int) int <span class="cov2" title="3">{ 384 var sum int 385 386 var start int 387 388 if len(calories) > 3 </span><span class="cov2" title="3">{ 389 start += len(calories) - 3 390 }</span> 391 392 <span class="cov2" title="3">sort.Ints(calories) 393 394 for _, calorie := range calories[start:] </span><span class="cov3" title="9">{ 395 sum += calorie 396 }</span> 397 398 <span class="cov2" title="3">return sum</span> 399 } 400 401 func getResultTopThreeCalories(data map[string]int) int <span class="cov1" title="2">{ 402 totals := []int{} 403 404 for _, calories := range data </span><span class="cov6" title="246">{ 405 totals = append(totals, calories) 406 }</span> 407 408 <span class="cov1" title="2">result := getTopThreeSum(totals) 409 410 return result</span> 411 } 412 </pre> 413 414 <pre class="file" id="file6" style="display: none">// Package day01 is the module with the cli logic for the cmd application. 415 package day01 416 417 // Config holds the application's configuration. 418 type Config struct { 419 appName string 420 inputFileName string 421 } 422 423 // Setup creates the applications configuration object. 424 func Setup(appName string) Config <span class="cov10" title="4">{ 425 426 conf := Config{ 427 appName: appName, 428 inputFileName: "data/" + appName + "/" + appName + "-input.txt", 429 } 430 431 return conf 432 }</span> 433 </pre> 434 435 <pre class="file" id="file7" style="display: none">// Package day02 is the module with the cli logic for the application. 436 package day02 437 438 import ( 439 "bufio" 440 "fmt" 441 "strings" 442 443 "github.com/vpayno/adventofcode-2022-golang-workspace/internal/aocshared" 444 ) 445 446 // Run is called my the gain function. It's basically the main function of the app. 447 func Run(conf Config) error <span class="cov2" title="3">{ 448 file, err := aocshared.GetFile(conf.inputFileName) 449 if err != nil </span><span class="cov1" title="1">{ 450 return err 451 }</span> 452 453 <span class="cov1" title="2">scanner := aocshared.GetScanner(file) 454 455 data, err := loadData(scanner) 456 if err != nil </span><span class="cov1" title="1">{ 457 return err 458 }</span> 459 460 <span class="cov1" title="1">totalScore := getTotalScore(data) 461 462 aocshared.ShowResult(totalScore) 463 464 return nil</span> 465 } 466 467 func loadData(file *bufio.Scanner) (rounds, error) <span class="cov2" title="4">{ 468 var err error 469 470 data := rounds{} 471 472 for file.Scan() </span><span class="cov10" title="5018">{ 473 line := file.Text() 474 475 if line == "" </span><span class="cov1" title="2">{ 476 continue</span> 477 } 478 479 <span class="cov9" title="5016">s := strings.Fields(line) 480 481 if len(s) != 2 </span><span class="cov1" title="2">{ 482 err := fmt.Errorf("wrong number of records: has %d, need %d", len(s), 2) 483 return []round{}, err 484 }</span> 485 486 <span class="cov9" title="5014">theirMove := string2move[s[them]] 487 yourGoal := string2outcome[s[goal]] 488 489 r := round{ 490 them: theirMove, 491 goal: yourGoal, 492 } 493 494 data = append(data, r)</span> 495 } 496 497 <span class="cov1" title="2">return data, err</span> 498 } 499 500 func getTotalScore(data rounds) int <span class="cov1" title="2">{ 501 var result int 502 503 for _, r := range data </span><span class="cov9" title="2503">{ 504 result += r.score() 505 }</span> 506 507 <span class="cov1" title="2">return result</span> 508 } 509 </pre> 510 511 <pre class="file" id="file8" style="display: none">// Package day02 is the module with the cli logic for the cmd application. 512 package day02 513 514 // Config holds the application's configuration. 515 type Config struct { 516 appName string 517 inputFileName string 518 } 519 520 // record ids (columns in input file) 521 const ( 522 them int = iota 523 goal 524 ) 525 526 // Outcome describes the possible outcomes. 527 type outcome int 528 529 const ( 530 loose outcome = 0 531 draw outcome = 3 532 win outcome = 6 533 ) 534 535 var outcomeNames = map[outcome]string{ 536 loose: "loose", 537 draw: "draw", 538 win: "win", 539 } 540 541 // Move descrives possible moves. 542 type move int 543 544 const ( 545 rock move = 1 546 paper move = 2 547 scissors move = 3 548 ) 549 550 var moveNames = map[move]string{ 551 rock: "rock", 552 paper: "paper", 553 scissors: "scissors", 554 } 555 556 var string2move = map[string]move{ 557 "A": rock, 558 "B": paper, 559 "C": scissors, 560 } 561 562 var string2outcome = map[string]outcome{ 563 "X": loose, 564 "Y": draw, 565 "Z": win, 566 } 567 568 // Round describes one round of rock-paper-scissors. 569 type round struct { 570 them move 571 goal outcome 572 } 573 574 func (r *round) yourMove() move <span class="cov10" title="2521">{ 575 var you move 576 577 switch r.goal </span>{ 578 case loose:<span class="cov7" title="411"> 579 switch r.them </span>{ 580 case rock:<span class="cov5" title="43"> 581 you = scissors</span> 582 case paper:<span class="cov7" title="323"> 583 you = rock</span> 584 case scissors:<span class="cov5" title="45"> 585 you = paper</span> 586 } 587 case win:<span class="cov8" title="848"> 588 switch r.them </span>{ 589 case rock:<span class="cov6" title="84"> 590 you = paper</span> 591 case paper:<span class="cov7" title="225"> 592 you = scissors</span> 593 case scissors:<span class="cov8" title="539"> 594 you = rock</span> 595 } 596 default:<span class="cov9" title="1262"> 597 you = r.them</span> 598 } 599 600 <span class="cov10" title="2521">return you</span> 601 } 602 603 func (r *round) score() int <span class="cov9" title="2512">{ 604 return int(r.goal) + int(r.yourMove()) 605 }</span> 606 607 func (r *round) update(slice []move) <span class="cov1" title="1">{ 608 r.them = slice[them] 609 r.goal = outcome(int(slice[goal])) 610 }</span> 611 612 type rounds []round 613 614 // Setup creates the applications configuration object. 615 func Setup(appName string) Config <span class="cov2" title="4">{ 616 617 conf := Config{ 618 appName: appName, 619 inputFileName: "data/" + appName + "/" + appName + "-input.txt", 620 } 621 622 return conf 623 }</span> 624 </pre> 625 626 <pre class="file" id="file9" style="display: none">// Package day03 is the module with the cli logic for the application. 627 package day03 628 629 import ( 630 "bufio" 631 "fmt" 632 633 "github.com/vpayno/adventofcode-2022-golang-workspace/internal/aocshared" 634 ) 635 636 // Run is called my the gain function. It's basically the main function of the app. 637 func Run(conf Config) error <span class="cov3" title="6">{ 638 file, err := aocshared.GetFile(conf.inputFileName) 639 if err != nil </span><span class="cov1" title="2">{ 640 return err 641 }</span> 642 643 <span class="cov2" title="4">scanner := aocshared.GetScanner(file) 644 645 data, err := loadData(scanner) 646 if err != nil </span><span class="cov1" title="1">{ 647 return err 648 }</span> 649 650 <span class="cov2" title="3">prioritySum, err := getPrioritySum(data) 651 if err != nil </span><span class="cov1" title="1">{ 652 return err 653 }</span> 654 655 <span class="cov1" title="2">aocshared.ShowResult(prioritySum) 656 657 groupPrioritySum, err := getGroupPrioritySum(data) 658 if err != nil </span><span class="cov1" title="1">{ 659 return err 660 }</span> 661 662 <span class="cov1" title="1">aocshared.ShowResult(groupPrioritySum) 663 664 return nil</span> 665 } 666 667 func loadData(file *bufio.Scanner) (rucksacks, error) <span class="cov3" title="7">{ 668 data := rucksacks{} 669 670 for file.Scan() </span><span class="cov10" title="907">{ 671 line := file.Text() 672 673 if line == "" </span><span class="cov1" title="1">{ 674 continue</span> 675 } 676 677 <span class="cov9" title="906">r := rucksack{} 678 err := r.addItems(line) 679 if err != nil </span><span class="cov2" title="3">{ 680 return data, err 681 }</span> 682 683 <span class="cov9" title="903">data = append(data, r)</span> 684 } 685 686 <span class="cov2" title="4">return data, nil</span> 687 } 688 689 func getPrioritySum(data rucksacks) (int, error) <span class="cov3" title="5">{ 690 var result int 691 692 for _, r := range data </span><span class="cov9" title="608">{ 693 priority, err := r.getSharedPriority() 694 if err != nil </span><span class="cov1" title="2">{ 695 return 0, err 696 }</span> 697 698 <span class="cov9" title="606">result += priority</span> 699 } 700 701 <span class="cov2" title="3">return result, nil</span> 702 } 703 704 func getGroupPrioritySum(data rucksacks) (int, error) <span class="cov3" title="5">{ 705 var groupSum int 706 group := []string{} 707 sacks := [][]string{} 708 709 if len(data) == 0 </span><span class="cov1" title="1">{ 710 err := fmt.Errorf("rucksack list is empty: %v", data) 711 return 0, err 712 }</span> 713 714 <span class="cov2" title="4">if len(data)%3 != 0 </span><span class="cov1" title="2">{ 715 err := fmt.Errorf("rucksack list length, %d, isn't evenly divisible by 3", len(data)) 716 return 0, err 717 }</span> 718 719 <span class="cov1" title="2">for i, r := range data </span><span class="cov8" title="306">{ 720 if i%3 == 0 && i > 0 </span><span class="cov7" title="100">{ 721 sacks = append(sacks, group) 722 group = []string{} 723 }</span> 724 725 <span class="cov8" title="306">group = append(group, r.items)</span> 726 } 727 728 <span class="cov1" title="2">sacks = append(sacks, group) 729 730 for _, group := range sacks </span><span class="cov7" title="102">{ 731 // not handling the case where the number of rucksacks isn't evenly divisibleby 3 732 g1 := aocshared.SetFromSlice(aocshared.SplitString(group[0])) 733 g2 := aocshared.SetFromSlice(aocshared.SplitString(group[1])) 734 g3 := aocshared.SetFromSlice(aocshared.SplitString(group[2])) 735 736 c1 := aocshared.SetFromSlice(aocshared.SetIntersect(g1, g2)) 737 c2 := aocshared.SetFromSlice(aocshared.SetIntersect(g1, g3)) 738 c3 := aocshared.SetFromSlice(aocshared.SetIntersect(g2, g3)) 739 740 c1 = aocshared.SetFromSlice(aocshared.SetIntersect(c1, c2)) 741 c1 = aocshared.SetFromSlice(aocshared.SetIntersect(c1, c3)) 742 743 for item := range c1 </span><span class="cov7" title="102">{ 744 priority := getPriority(item) 745 groupSum += priority 746 }</span> 747 } 748 749 <span class="cov1" title="2">return groupSum, nil</span> 750 } 751 </pre> 752 753 <pre class="file" id="file10" style="display: none">// Package day03 is the module with the cli logic for the cmd application. 754 package day03 755 756 import ( 757 "errors" 758 "fmt" 759 "strings" 760 "unicode" 761 ) 762 763 // Config holds the application's configuration. 764 type Config struct { 765 appName string 766 inputFileName string 767 } 768 769 // Rucksack holds an Elf's items. 770 type rucksack struct { 771 items string 772 } 773 774 func (r *rucksack) addItems(items string) error <span class="cov8" title="922">{ 775 if len(items)%2 != 0 </span><span class="cov2" title="4">{ 776 return fmt.Errorf("items list isn't evenly divisible (len=%d)", len(items)) 777 }</span> 778 779 <span class="cov8" title="918">r.items = items 780 781 return nil</span> 782 } 783 784 func (r *rucksack) getCollection(num int) string <span class="cov8" title="1226">{ 785 786 if num == 1 </span><span class="cov7" title="613">{ 787 return r.items[0 : len(r.items)/2] 788 }</span> 789 790 <span class="cov7" title="613">return r.items[len(r.items)/2:]</span> 791 } 792 793 // lot's of room or optimizations 794 func (r *rucksack) getSharedItem() (rune, error) <span class="cov7" title="612">{ 795 collection1 := r.getCollection(1) 796 collection2 := r.getCollection(2) 797 798 for _, char := range collection1 </span><span class="cov10" title="4466">{ 799 if strings.ContainsRune(collection2, char) </span><span class="cov7" title="608">{ 800 return char, nil 801 }</span> 802 } 803 804 <span class="cov2" title="4">return rune(0), errors.New("rucksack compartments doesn't have a shared item")</span> 805 } 806 807 func (r *rucksack) getSharedPriority() (int, error) <span class="cov7" title="610">{ 808 shared, err := r.getSharedItem() 809 if err != nil </span><span class="cov2" title="3">{ 810 return 0, err 811 }</span> 812 813 <span class="cov7" title="607">return getPriority(shared), nil</span> 814 } 815 816 type rucksacks []rucksack 817 818 // Setup creates the applications configuration object. 819 func Setup(appName string) Config <span class="cov3" title="7">{ 820 821 conf := Config{ 822 appName: appName, 823 inputFileName: "data/" + appName + "/" + appName + "-input.txt", 824 } 825 826 return conf 827 }</span> 828 829 func getPriority(item rune) int <span class="cov8" title="713">{ 830 if unicode.IsLower(item) </span><span class="cov7" title="322">{ 831 return int(item) - 96 832 }</span> 833 834 <span class="cov7" title="391">return int(item) - 38</span> 835 } 836 </pre> 837 838 <pre class="file" id="file11" style="display: none">// Package day04 is the module with the cli logic for the application. 839 package day04 840 841 import ( 842 "bufio" 843 844 "github.com/vpayno/adventofcode-2022-golang-workspace/internal/aocshared" 845 ) 846 847 // Run is called my the gain function. It's basically the main function of the app. 848 func Run(conf Config) error <span class="cov3" title="8">{ 849 file, err := aocshared.GetFile(conf.inputFileName) 850 if err != nil </span><span class="cov1" title="1">{ 851 return err 852 }</span> 853 854 <span class="cov3" title="7">scanner := aocshared.GetScanner(file) 855 856 data, err := loadData(scanner) 857 if err != nil </span><span class="cov3" title="6">{ 858 return err 859 }</span> 860 861 <span class="cov1" title="1">fullyContainedSum := getFullyContainedCount(data) 862 863 aocshared.ShowResult(fullyContainedSum) 864 865 partiallyContainedSum := getPartiallyContainedCount(data) 866 867 aocshared.ShowResult(partiallyContainedSum) 868 869 return nil</span> 870 } 871 872 func loadData(file *bufio.Scanner) (pairs, error) <span class="cov4" title="15">{ 873 data := pairs{} 874 875 for file.Scan() </span><span class="cov10" title="2029">{ 876 line := file.Text() 877 878 if line == "" </span><span class="cov1" title="1">{ 879 continue</span> 880 } 881 882 <span class="cov9" title="2028">p := pair{} 883 err := p.addPair(line) 884 if err != nil </span><span class="cov3" title="12">{ 885 return data, err 886 }</span> 887 888 <span class="cov9" title="2016">data = append(data, p)</span> 889 } 890 891 <span class="cov2" title="3">return data, nil</span> 892 } 893 894 func getFullyContainedCount(data pairs) int <span class="cov1" title="2">{ 895 var count int 896 897 for _, p := range data </span><span class="cov9" title="1006">{ 898 if p.isFullyContained(1) || p.isFullyContained(2) </span><span class="cov8" title="500">{ 899 count++ 900 }</span> 901 } 902 903 <span class="cov1" title="2">return count</span> 904 } 905 906 func getPartiallyContainedCount(data pairs) int <span class="cov1" title="2">{ 907 var count int 908 909 for _, p := range data </span><span class="cov9" title="1006">{ 910 if p.isPartiallyContained(1) || p.isPartiallyContained(2) </span><span class="cov8" title="863">{ 911 count++ 912 }</span> 913 } 914 915 <span class="cov1" title="2">return count</span> 916 } 917 </pre> 918 919 <pre class="file" id="file12" style="display: none">// Package day04 is the module with the cli logic for the cmd application. 920 package day04 921 922 import ( 923 "fmt" 924 "strconv" 925 "strings" 926 ) 927 928 // Config holds the application's configuration. 929 type Config struct { 930 appName string 931 inputFileName string 932 } 933 934 // Section stores the start and end range of an Elf's section. 935 type section struct { 936 start int 937 end int 938 } 939 940 func (s *section) addRange(r string) error <span class="cov10" title="4075">{ 941 data := strings.Split(r, "-") 942 943 if len(data) != 2 </span><span class="cov1" title="2">{ 944 return fmt.Errorf("range did not contain start and end values (%v)", data) 945 }</span> 946 947 <span class="cov9" title="4073">var err error 948 949 start, err := strconv.Atoi(data[0]) 950 if err != nil </span><span class="cov1" title="2">{ 951 return err 952 }</span> 953 954 <span class="cov9" title="4071">end, err := strconv.Atoi(data[1]) 955 if err != nil </span><span class="cov1" title="2">{ 956 return err 957 }</span> 958 959 <span class="cov9" title="4069">if start < 1 </span><span class="cov1" title="2">{ 960 return fmt.Errorf("range start, %d, is less than 1", start) 961 }</span> 962 963 <span class="cov9" title="4067">if end > 99 </span><span class="cov1" title="2">{ 964 return fmt.Errorf("range end, %d, is greather than 99", end) 965 }</span> 966 967 <span class="cov9" title="4065">s.start = start 968 s.end = end 969 970 return nil</span> 971 } 972 973 // Pair holds 2 elves sections. 974 type pair struct { 975 elf1 section 976 elf2 section 977 } 978 979 func (p *pair) addPair(input string) error <span class="cov9" title="2042">{ 980 data := strings.Split(input, ",") 981 982 if len(data) != 2 </span><span class="cov1" title="2">{ 983 return fmt.Errorf("input list doesn't contain two entries (%v)", data) 984 }</span> 985 986 <span class="cov9" title="2040">err := p.elf1.addRange(data[0]) 987 if err != nil </span><span class="cov2" title="6">{ 988 return err 989 }</span> 990 991 <span class="cov9" title="2034">err = p.elf2.addRange(data[1]) 992 if err != nil </span><span class="cov2" title="4">{ 993 return err 994 }</span> 995 996 <span class="cov9" title="2030">return nil</span> 997 } 998 999 func (p *pair) isFullyContained(elfNo int) bool <span class="cov9" title="1749">{ 1000 if elfNo == 1 </span><span class="cov8" title="1007">{ 1001 return p.elf1.start >= p.elf2.start && p.elf1.end <= p.elf2.end 1002 }</span> 1003 1004 <span class="cov8" title="742">return p.elf2.start >= p.elf1.start && p.elf2.end <= p.elf1.end</span> 1005 } 1006 1007 func (p *pair) isPartiallyContained(elfNo int) bool <span class="cov8" title="1238">{ 1008 if elfNo == 1 </span><span class="cov8" title="1006">{ 1009 return (p.elf2.start <= p.elf1.start && p.elf1.start <= p.elf2.end) || (p.elf2.start <= p.elf1.end && p.elf1.end <= p.elf2.end) 1010 }</span> 1011 1012 <span class="cov6" title="232">return (p.elf1.start <= p.elf2.start && p.elf2.start <= p.elf1.end) || (p.elf1.start <= p.elf2.end && p.elf2.end <= p.elf1.end)</span> 1013 } 1014 1015 type pairs []pair 1016 1017 // Setup creates the applications configuration object. 1018 func Setup(appName string) Config <span class="cov3" title="9">{ 1019 1020 conf := Config{ 1021 appName: appName, 1022 inputFileName: "data/" + appName + "/" + appName + "-input.txt", 1023 } 1024 1025 return conf 1026 }</span> 1027 </pre> 1028 1029 </div> 1030 </body> 1031 <script> 1032 (function() { 1033 var files = document.getElementById('files'); 1034 var visible; 1035 files.addEventListener('change', onChange, false); 1036 function select(part) { 1037 if (visible) 1038 visible.style.display = 'none'; 1039 visible = document.getElementById(part); 1040 if (!visible) 1041 return; 1042 files.value = part; 1043 visible.style.display = 'block'; 1044 location.hash = part; 1045 } 1046 function onChange() { 1047 select(files.value); 1048 window.scrollTo(0, 0); 1049 } 1050 if (location.hash != "") { 1051 select(location.hash.substr(1)); 1052 } 1053 if (!visible) { 1054 select("file0"); 1055 } 1056 })(); 1057 </script> 1058 </html>