Я новичок в изучении 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
который не принимает оператор +.
Я хотел бы увидеть возможную реализацию этой проблемы. Спасибо за ваше время!
ты очень близок, так что сказать тебе было бы все испортить.
Вы не против поделиться этим? Как бы это выглядело
проблема здесь в том, что эта группа получает сообщения от людей, которые хотят, чтобы вы сделали их домашнюю работу .... поэтому люди очень нервничают из-за явного предоставления вам полного ответа.
Да, я вижу это. Я думаю, люди счастливее оставить вопрос без ответа
Это домашнее задание? или просто что-то, что вы пытаетесь сделать?
Нет, просто хочу узнать больше об этом языке
Я новичок в изучении 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.
Лично я бы определил свой собственный 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 =
@BillyFitt Я бы получил исходную проблему и попытался бы работать, прежде чем пробовать расширения или альтернативы. Вам нужно создать функцию, которая, учитывая Cards
и int list
возможных баллов от оставшихся карточек, будет возвращать int list
всех возможных баллов. У вас уже есть функция, которая дает вам возможные баллы от карт. Это можно использовать для упрощения задачи, исключив Cards
, поэтому на оставшемся шаге вам нужно работать только с целыми числами.
Первоначальная проблема - это то, о чем я спросил в своем посте. Не могли бы вы показать мне, как это сделать, я имею в виду использование моей в настоящее время неиспользуемой функции cardvalue и другой небольшой шаг - я почему-то все еще не мог заставить ее работать
Ну, ваша функцияcardsValue дает вам возможные значения первой карты (int list
), а рекурсия дает вам tailPoints
, еще одну int list
. Таким образом, задача сводится к следующему: по двум int list
найти все возможные суммы. Для этого вам может быть полезно использовать функции List.map
и List.concat
или, в качестве альтернативы, использовать синтаксис «выход» для построения списка [ for x in someSequence do yield f(x) ]
.
Вот 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)
.
Хорошо, ваш ответ очень близок. но вы пытаетесь добавить «карту» в список целых чисел. то, что вы хотите сделать, это взять каждое возможное значение карты и добавить его к каждому возможному значению суммы остальных карт.
Хорошо, я, вероятно, не стал бы делать это так, но, возможно, это самый простой ответ для понимания (при условии, что вы понимаете понимание списков).
Это также не совсем идеально функционально, но я оставлю это вам, чтобы выяснить и исправить.
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
.
Я не проверял это, неявные выходы поддерживаются в F#, поэтому в моей голове это работает, это даст дубликаты.
вы пытаетесь добавить номер в список номеров