Сумма предопределенного списка F#

Я новичок в изучении F#, в настоящее время пробую некоторые действия со списками в реализации BlackJack F#.

Я пытаюсь суммировать элементы списка, который я создал следующим образом:

let cardsvalue (k: Cards): List<int> =
    match k with
    |Ace ->  [1;11]
    |Two -> [2] 
    |Three -> [3]
    |Four -> [4]
    |Five -> [5]
    |Six -> [6]
    |Seven -> [7]
    |Eight -> [8]
    |Nine -> [9]
    |Ten | Jack | Queen | King -> [10] 

type Cards — это просто союз карт от двойки до девятки, от десятки до короля и туза.

Поэтому мне нужна какая-то рекурсивная функция CardPoints, которая просто добавляет элементы из cardsvalue, например [Two; Three] = [5] или [Ace; Ace; Ace] = [3; 13; 23; 33], что означает все возможные значения туза. Я пробовал несколько распространенных способов получения суммы, но всегда получаю несоответствие типов или не поддерживаю ошибку оператора. Например

let rec CardPoints (cp: List<Cards>): List<int> =   
   match cp with
   | head :: tail -> head + CardPoints tail
   | [] -> 0 

который не принимает оператор +.

Я хотел бы увидеть возможную реализацию этой проблемы. Спасибо за ваше время!

вы пытаетесь добавить номер в список номеров

MrD at KookerellaLtd 20.12.2020 18:12

ты очень близок, так что сказать тебе было бы все испортить.

MrD at KookerellaLtd 20.12.2020 18:24

Вы не против поделиться этим? Как бы это выглядело

Billy Fitt 21.12.2020 21:25

проблема здесь в том, что эта группа получает сообщения от людей, которые хотят, чтобы вы сделали их домашнюю работу .... поэтому люди очень нервничают из-за явного предоставления вам полного ответа.

MrD at KookerellaLtd 24.12.2020 10:47

Да, я вижу это. Я думаю, люди счастливее оставить вопрос без ответа

Billy Fitt 25.12.2020 18:27

Это домашнее задание? или просто что-то, что вы пытаетесь сделать?

MrD at KookerellaLtd 26.12.2020 13:17

Нет, просто хочу узнать больше об этом языке

Billy Fitt 27.12.2020 09:54
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
7
126
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я новичок в изучении F#

Ваш код демонстрирует хороший систематический подход, и вы уже проделали большую часть работы, чтобы позволить системе типов (и intellisense) помочь решить вашу проблему.

let cardsvalue (k: Cards): List<int> =

Полезная функция с точно правильной сигнатурой типа. Обратите внимание, что он неактивен. Это означает, что вы не используете его.

let rec CardPoints (cp: List<Cards>): List<int> =

Тоже точно правильно. Вы оказываете максимально возможную помощь системе типов, что делает почти уверенным, что она определит точную точку, в которой что-то идет не так.

Я всегда получаю несоответствие типов или не поддерживаю ошибку оператора. Например

    | head :: tail -> head + CardPoints tail

Попробуйте использовать привязку, чтобы понять это:

    | head :: tail ->
        let tailPoints = CardPoints tail
        head + tailPoints

Вы можете сказать (наведя на них курсор), что head — это Cards, а tailPoints — это List<int>. Итак, вы пытаетесь добавить Cards к List<int>, и такая операция добавления не определена.

Итак, вы сократили это до более мелкой задачи: учитывая карту (head: Cards) и возможные очки (tailPoints: List<int>) от оставшихся карт, как вы можете найти возможные очки от всех карт, которые должны быть List<int>? Вам нужно будет использовать текущую неиспользуемую функцию cardsvalue и еще один небольшой шаг, и вы там.

Не могли бы вы показать, как это делается, я не могу заставить его работать. И последний вопрос — как бы вы реализовали условие, чтобы туз не набирал больше 21, например, [Ace;Ace;Ace] должно быть всего 13 (1+1+11), а [Ace; Five; Ace] должно быть 17.

Billy Fitt 21.12.2020 14:08

Лично я бы определил свой собственный type Points = Hard of int | Soft of int*int, а затем использовал бы что-то вроде этого match cp with | Hard x -> Hard x | Soft(x,y) -> if y > 21 then Hard x else Soft(x,y), но это потребовало бы от меня переписать все заново. Можете ли вы показать мне, как это будет выглядеть, если мы используем, например, третью функцию let CalScore (cp: List<Cards>): int =

Billy Fitt 21.12.2020 14:08

@BillyFitt Я бы получил исходную проблему и попытался бы работать, прежде чем пробовать расширения или альтернативы. Вам нужно создать функцию, которая, учитывая Cards и int list возможных баллов от оставшихся карточек, будет возвращать int list всех возможных баллов. У вас уже есть функция, которая дает вам возможные баллы от карт. Это можно использовать для упрощения задачи, исключив Cards, поэтому на оставшемся шаге вам нужно работать только с целыми числами.

Charles Roddie 21.12.2020 20:37

Первоначальная проблема - это то, о чем я спросил в своем посте. Не могли бы вы показать мне, как это сделать, я имею в виду использование моей в настоящее время неиспользуемой функции cardvalue и другой небольшой шаг - я почему-то все еще не мог заставить ее работать

Billy Fitt 21.12.2020 20:44

Ну, ваша функцияcardsValue дает вам возможные значения первой карты (int list), а рекурсия дает вам tailPoints, еще одну int list. Таким образом, задача сводится к следующему: по двум int list найти все возможные суммы. Для этого вам может быть полезно использовать функции List.map и List.concat или, в качестве альтернативы, использовать синтаксис «выход» для построения списка [ for x in someSequence do yield f(x) ].

Charles Roddie 21.12.2020 22:21

Вот 3 решения последней проблемы: let allSums(l1:int list, l2:int list) = [ for x in l1 do for y in l2 do yield x + y ]. let allSums2(l1:int list, l2:int list) = l1 |> List.map (fun x -> l2 |> List.map (fun y -> x + y)) |> List.concat. let rec allSums3(l1:int list, l2:int list) = match l1 with | [] -> [] | h :: t -> (l2 |> List.map (fun y -> y + h)) @ allSums3(t, l2).

Charles Roddie 22.12.2020 12:56
Ответ принят как подходящий

Хорошо, ваш ответ очень близок. но вы пытаетесь добавить «карту» в список целых чисел. то, что вы хотите сделать, это взять каждое возможное значение карты и добавить его к каждому возможному значению суммы остальных карт.

Хорошо, я, вероятно, не стал бы делать это так, но, возможно, это самый простой ответ для понимания (при условии, что вы понимаете понимание списков).

Это также не совсем идеально функционально, но я оставлю это вам, чтобы выяснить и исправить.

let rec cardPoints (cp: List<Card>): List<int> =   
   match cp with
   | head :: tail -> 
        [ for val1 in cardsvalue head do
            for val2 in cardPoints tail do 
                val1 + val2 ]
   | [] -> [0]

Спасибо! Возможно, вы захотите изменить yield на val1 + val2.

Billy Fitt 27.12.2020 23:15

Я не проверял это, неявные выходы поддерживаются в F#, поэтому в моей голове это работает, это даст дубликаты.

MrD at KookerellaLtd 28.12.2020 10:02

Другие вопросы по теме