Solución de Clojure a Hackerank Challenge 'Restaurante' bajo la teoría del número -- programming-challenge campo con clojure camp codereview Relacionados El problema

Clojure solution to HackerRank Challenge 'Restaurant' under Number Theory


3
vote

problema

Español

Mi principal preocupación es lo sucesivo que es la función min-number-of-slices . Agradecería ayuda para encontrar buenas formas de limpiarlo, ya que tiene mucha anidación / alcance.

Este es mi primer programa de Clojure, así que sé que esto probablemente no sea un engaño idiomático, ni está limpio, ni probablemente rápido, tampoco. Por favor, dé tantos comentarios que desee en mi código (especialmente con respecto a las cosas que sean malas).

El desafío es, dada una lista de dimensiones 2D para piezas de pan, encuentre el número mínimo de cuadrados perfectos que pueda cortar de cada pieza sin perder ningún pan. https://www.hackerrank.com/challenges/restaurant

  (ns clojure-solution.core) (require '[clojure.string :as string])  (defn parse-int [s]   (Integer. s))  (defn parse-line [s]   (map parse-int (string/split s #" ")))  (defn get-loaf-dimensions []   (let [numLoaves (parse-int (read-line))]     (map #(%1) (repeat numLoaves (comp parse-line read-line)))))  (def squares (map #(* % %) (range 1 1001)))  (defn min-number-of-slices [dims]   (let [l              (first dims)         b              (second dims)         area           (* l b)]     (letfn [(perfect-slice-dimension? [slice-area]               (= 0 (+ (mod area slice-area)                       (mod b (int (Math/sqrt slice-area)))                       (mod l (int (Math/sqrt slice-area))))))]       (let [largest-square (last (filter perfect-slice-dimension? (take (min l b) squares)))]         (int (/ area largest-square))))))  (defn -main [& args] (dorun (map println (map min-number-of-slices (get-loaf-dimensions)))))   
Original en ingles

My main concern is how messy the min-number-of-slices function is. I would appreciate help finding good ways to clean that up since it has a lot of nesting/scope.

This is my first ever Clojure program, so I know this is probably not idiomatic Clojure, nor is it neat, nor probably fast, either. Please give as much feedback as you would like on my code (especially regarding stuff that's bad about it).

The challenge is, given a list of 2D dimensions for pieces of bread, find the minimum number of perfect squares you could cut out of each piece without wasting any bread. https://www.hackerrank.com/challenges/restaurant

(ns clojure-solution.core) (require '[clojure.string :as string])  (defn parse-int [s]   (Integer. s))  (defn parse-line [s]   (map parse-int (string/split s #" ")))  (defn get-loaf-dimensions []   (let [numLoaves (parse-int (read-line))]     (map #(%1) (repeat numLoaves (comp parse-line read-line)))))  (def squares (map #(* % %) (range 1 1001)))  (defn min-number-of-slices [dims]   (let [l              (first dims)         b              (second dims)         area           (* l b)]     (letfn [(perfect-slice-dimension? [slice-area]               (= 0 (+ (mod area slice-area)                       (mod b (int (Math/sqrt slice-area)))                       (mod l (int (Math/sqrt slice-area))))))]       (let [largest-square (last (filter perfect-slice-dimension? (take (min l b) squares)))]         (int (/ area largest-square))))))  (defn -main [& args] (dorun (map println (map min-number-of-slices (get-loaf-dimensions))))) 
     
   
   

Lista de respuestas

2
 
vote
vote
La mejor respuesta
 
  ;(ns clojure-solution.core) ;(require '[clojure.string :as string])   

Normalmente, solo usa las funciones requeridas, usadas e importaciones en el rez. La macro de NS apoya a todos aquellos y reduce la cantidad de citando que necesitas.

  (ns clojure-solution.core   (:require [clojure.string :as string]))  (defn parse-int [s]   (Integer. s))  (defn parse-line [s]   (map parse-int (string/split s #" ")))   

Tenga cuidado con los efectos secundarios (como la línea de lectura) en secuencias. Su código definitivamente funciona porque obligas a la evaluación con Dorun Down en -principal. También puede usar Doall aquí para evaluar la secuencia y devolver el resultado.

  (defn get-loaf-dimensions []   (let [numLoaves (parse-int (read-line))]     (map #(%1) (repeat numLoaves (comp parse-line read-line)))))  (def squares (map #(* % %) (range 1 1001)))   

No hay grandes cambios aquí, pero usando apply a continuación le permite usar argumentos ordinarios Aquí, en lugar de desempacar la lista dentro de la función. Otro La opción Si realmente necesitaba pasar una lista sería usar la destrucción: en este caso (defn min-number-of-slices [[l b]]) Tomaría los dos primeros elementos de la lista y los enlazaría a L y B. La destrucción también funciona dentro de la sede: (let [[l b] dims]])

También solo necesita letfn si tiene varias funciones que se refieren entre sí. Es un engaño perfectamente idiomático para simplemente unir una función anónima a un nombre. Mi comprensión es que Letfn se comporta más como alquiler en Haskell (solo restringido a las funciones).

  (defn min-number-of-slices [l b]   (let [area (* l b)         perfect-slice-dimension?          (fn [slice-area]                (= 0 (+ (mod area slice-area)                       (mod b (int (Math/sqrt slice-area)))                       (mod l (int (Math/sqrt slice-area))))))]       (let [largest-square (last (filter perfect-slice-dimension? (take (min l b) squares)))]         (int (/ area largest-square)))))   

apply8 toma una función y una lista (o cualquier cosa que se pueda tratar como una secuencia) y usa la lista como argumentos a la función:

  (defn -main [& args] (dorun (map println (map (partial apply min-number-of-slices) (get-loaf-dimensions)))))   
 
;(ns clojure-solution.core) ;(require '[clojure.string :as string]) 

Typically you only use the require, use, and import functions in the REPL. The ns macro supports all of those and it reduces the amount of quoting you need.

(ns clojure-solution.core   (:require [clojure.string :as string]))  (defn parse-int [s]   (Integer. s))  (defn parse-line [s]   (map parse-int (string/split s #" "))) 

Be careful with side effects (like read-line) in sequences. Your code definitely works because you force evaluation with dorun down in -main. You could also use doall here to evaluate the sequence and return the result.

(defn get-loaf-dimensions []   (let [numLoaves (parse-int (read-line))]     (map #(%1) (repeat numLoaves (comp parse-line read-line)))))  (def squares (map #(* % %) (range 1 1001))) 

No huge changes here but using apply below lets you use ordinary arguments here instead of unpacking the list inside the function. Another option if you really needed to pass a list would be to use destructring: in this case (defn min-number-of-slices [[l b]]) would take the first two items of the list and bind them to l and b. Destructuring also works inside of let: (let [[l b] dims]])

Also you only need letfn if you have multiple functions that refer to each other. It's perfectly idiomatic Clojure to just bind an anonymous function to a name. My understanding is that letfn behaves more like let in Haskell (only restricted to just functions).

(defn min-number-of-slices [l b]   (let [area (* l b)         perfect-slice-dimension?          (fn [slice-area]                (= 0 (+ (mod area slice-area)                       (mod b (int (Math/sqrt slice-area)))                       (mod l (int (Math/sqrt slice-area))))))]       (let [largest-square (last (filter perfect-slice-dimension? (take (min l b) squares)))]         (int (/ area largest-square))))) 

apply takes a function and a list (or anything that can be treated as a sequence) and uses the list as the arguments to the function:

(defn -main [& args] (dorun (map println (map (partial apply min-number-of-slices) (get-loaf-dimensions))))) 
 
 
 
 
3
 
vote

Ha implementado una solución de fuerza bruta, lo que intenta cada dimensión cuadrada de 1 hasta el mínimo de (ns clojure-solution.core (:require [clojure.string :as string])) (defn parse-int [s] (Integer. s)) (defn parse-line [s] (map parse-int (string/split s #" "))) 0 , (ns clojure-solution.core (:require [clojure.string :as string])) (defn parse-int [s] (Integer. s)) (defn parse-line [s] (map parse-int (string/split s #" "))) 1 y 1000.

El tamaño cuadrado óptimo es simplemente el mejor divisor común de (ns clojure-solution.core (:require [clojure.string :as string])) (defn parse-int [s] (Integer. s)) (defn parse-line [s] (map parse-int (string/split s #" "))) 2 y 99887766555443313 . Un algoritmo muy simple para calcular el GCD es el algoritmo euclidiano .

  (ns clojure-solution.core   (:require [clojure.string :as string]))  (defn parse-int [s]   (Integer. s))  (defn parse-line [s]   (map parse-int (string/split s #" "))) 4  

Cálculo del número mínimo de rodajas sigue fácilmente.

  (ns clojure-solution.core   (:require [clojure.string :as string]))  (defn parse-int [s]   (Integer. s))  (defn parse-line [s]   (map parse-int (string/split s #" "))) 5  

Puede intentar llamar (ns clojure-solution.core (:require [clojure.string :as string])) (defn parse-int [s] (Integer. s)) (defn parse-line [s] (map parse-int (string/split s #" "))) 6 en esta demostración de Clojescript:

  (ns clojure-solution.core   (:require [clojure.string :as string]))  (defn parse-int [s]   (Integer. s))  (defn parse-line [s]   (map parse-int (string/split s #" "))) 7  
  99887766555443318  
 

You've implemented a brute-force solution, trying every square dimension from 1 up to the minimum of l, b, and 1000.

The optimal square size is simply the greatest common divisor of l and b. A very simple algorithm to calculate the GCD is the Euclidean algorithm.

(defn gcd [a b]       (if (= b 0)            a            (gcd b (mod a b)))) 

Calculating the minimum number of slices follows easily.

(defn min-number-of-slices [l b]       (let [side (gcd l b)]            (/ (* l b) (* side side)))) 

You can try calling min-number-of-slices in this ClojureScript demo:

.code { font-family: Monaco, monospace; font-size: 10pt; } #log { height: 10em; overflow: auto; white-space: pre-wrap; } #input { width: 100%; height: 12em; }
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script><script type="text/javascript" src="https://kanaka.github.io/clojurescript/web/vendor/jq-console/jqconsole.min.js"></script><!-- script type="text/javascript" src="https://cdn.rawgit.com/google/closure-library/master/closure/goog/base.js"></script --><script type="text/javascript" src="https://kanaka.github.io/clojurescript/web/out/goog/base.js"></script><script type="text/javascript" src="https://kanaka.github.io/clojurescript/web/webrepl.js"></script><script type="text/javascript">goog.require('webrepl');</script> <div id="log" class="code"></div><textarea id="input" class="code" > (defn gcd [a b]         (if (= b 0)              a                          (gcd b (mod a b))))    (defn min-number-of-slices [l b]           (let [side (gcd l b)]                           (/ (* l b) (* side side))))    (min-number-of-slices 6 9) </textarea>
 
 
   
   

Relacionados problema

1  Ejercicio: limpiar y formatear un número de teléfono en Clojure  ( Exercism clean and format a phone number in clojure ) 
Declaración de problemas Número de teléfono Escriba un programa que limpie los números de teléfono ingresados ​​por el usuario para que puedan ser envi...

4  Envoltura API para Clojure  ( Api wrapper for clojure ) 
Quería envolver el biblioteca JeyMaster en una envoltura de Clojure (para mi propio uso, pero tal vez también para salvar a otros algún tiempo). Solo estoy ...

7  Cuerdas de partición en subcadenas de longitud fija  ( Partitioning strings into substrings of fixed length ) 
Tengo una función de Clojure aquí que está destinado a analizar una cadena de forma: "ddxxxyyy" Donde DD está destinado a ser descartado, y XXX y YYY so...

4  Encuentre los caracteres comunes entre dos cuerdas sin usar las operaciones establecidas  ( Find the common characters between two strings without using set operations ) 
A continuación se presentan dos implementaciones del problema "Encuentre los caracteres en común entre dos cadenas": en Clojure sin utilizar las operaciones d...

5  Fórmula Haversine en Clojure  ( Haversine formula in clojure ) 
Implementé el fórmula haversine para calcular la distancia entre dos (latitud , longitud) coordenadas. Me preguntaba si se ve natural para los programador...

2  Resolviendo la ecuación cuadrática en Clojure  ( Solving quadratic equation in clojure ) 
Escribí una función en Clojure para resolver ecuaciones cuadráticas utilizando la fórmula cuadrática la función (defn solvequadeq [a b c] (let [D (-...

25  Proyecto EULER PROBLEMA 2 EN COTJURE  ( Project euler problem 2 in clojure ) 
Estoy en el proceso de aprendizaje de Clojure. Soy bastante nuevo en la programación funcional y me gustaría saber si mi código huele o si hay alguna implicac...

1  Barajando muchas colecciones doblando sobre una gama numérica  ( Shuffling many collections by folding over a numeric range ) 
a menudo, me encuentro plegando sobre un objeto range si necesito transformar algo repetidamente. Esto, para mí, sin embargo, se siente como un abuso de fo...

13  Muestreo de reservorio en Clojure  ( Reservoir sampling in clojure ) 
Estoy aprendiendo a Clojure y decidí comenzar por intentar escribir una solución a un algoritmo bastante simple, un muestreo de reservorio. Como dije, estoy a...

11  ¿Es esta la forma en ello a Web-Scrape a una imagen de portada de libros?  ( Is this the clojure way to web scrape a book cover image ) 
¿Hay una manera de escribir esto mejor o más de manera de engaño? Especialmente la última parte con with-open y el let . ¿Debo poner el formulario 9988776...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos