Konvertieren Sie Singular in Plural

27

Es gibt zwei Formen von Substantiven: Singular und Plural. Die Konvertierung zwischen diesen beiden ist recht einfach.

  1. Normalerweise endet es mit s. Ex. car=> cars.

  2. Wenn es mit endet s, x, z, choder sh, beenden Sie ihn mit es. Ex. bus=> buses.

  3. Wenn es ymit einem Konsonanten endet , ändern Sie den Wert yin ies. Ex. penny=> pennies.

  4. Wenn es mit foder endet fe, ändern Sie es in ves. Ex. knife=> knives.

  5. Wenn es omit einem Konsonanten endet , ändern Sie es in oes. Ex. potato=> potatoes.


Aufgabe

Sie erhalten ein Substantiv. Sie müssen das angegebene Substantiv in Plural konvertieren und ausgeben.


Regeln

  • Sie erhalten keine unregelmäßigen Substantive wie mouseund moose.

  • Sie erhalten keine Ausnahmen wie safe( safes; Verletzung von # 4), piano( pianos; Verletzung von # 5) und o( oes; Verletzung von # 5).

  • Sie erhalten keine Wörter mit zwei oder mehr möglichen Pluralformen wie mosquito( mosquitosoder mosquitoes) und roof( roofsoder rooves).

  • Sie erhalten keine unzähligen Substantive.

  • y zählt nicht als Vokal.


Beispiele

car => cars
bus => buses
potato => potatoes
knife => knives
penny => pennies
exception => exceptions
wolf => wolves
eye => eyes
decoy => decoys
radio => radios
Matthew Roh
quelle
Editierte Frage zur Klarheit. Fühlen Sie sich frei, ein Rollback durchzuführen.
JungHwan Min
11
Ahh, Englisch - ein riesiger Haufen willkürlicher Regeln und Sonderfälle :)
Esolanging Fruit
38
@ Challenger5 Ja, aber man kann es durch gründliche Überlegungen verstehen. ;)
JungHwan Min
@MatthewRoh Ich habe den Konsonanten vor der Regel bearbeitet, um es klarer zu machen. Fügte auch ein paar Testfälle für das gleiche hinzu. Wenn ich es falsch verstanden habe, bearbeite es bitte, um es zu klären.
ghosts_in_the_code
2
@ Challenger5 Wenn Sie Englisch mit Niederländisch vergleichen, gibt es kaum Regeln. Niederländisch hat Regeln und Sonderfälle und Sonderfälle, die diesen Sonderfällen widersprechen, und in einigen Fällen sogar Sonderfälle, die diesen Sonderfällen widersprechen, die diesen Sonderfällen widersprechen. ;)
Kevin Cruijssen

Antworten:

46

Mathematica, 9 Bytes

Pluralize

Ja, dafür gibt es ein eingebautes!

Beispielausgabe

Pluralize["car"]

cars

Pluralize /@ {"bus", "potato", "knife", "penny", "exception", "wolf", "eye"}

{"buses", "potatoes", "knives", "pennies", "exceptions", "wolves", "eyes"}

JungHwan min
quelle
6
Waaaaaat! Gibt es etwas, für das Mathematica nicht eingebaut ist?
KeyWeeUsr
2
D: Builtins haben diese Herausforderung ebenfalls angegriffen
Matthew Roh
18

Retina , 57 53 56 55 58 57 Bytes

Vielen Dank an MartinEnder für einige Golfvorschläge

Vielen Dank an BusinessCat für das Golfen mit 1 Byte

([^aeiou]o|sh?|ch|z|x)$
$1e
fe?$
ve
([^aeiou])y$
$1ie
$
s

Probieren Sie es online!

Erklärung (veraltet)

([^aeiou])y$
$1ie

Änderungen {consonant}yan{consonant}ie

([^aeiou]o|[fxzs]|[sc]h)$
$&e

Hängt eine ean , wenn das Wort Ende mit einem {consonant}o, f, x, z, s, shoder ch.

fe$
ve

Ändert ein Ende fezuve

$
s

Fügen Sie szum Schluss ein an das Wort an.

Bearbeitungen

  • Bytes hinzugefügt, weil ich die zweite Regel vergessen habe
  • Hinzugefügt Bytes Update mit eyeals Beispiel
Kritixi Lithos
quelle
1
Sorry, wenn das eine blöde Frage ist, ich habe nicht Retina verwendet. Warum werden die runden Klammern in der ersten Zeile benötigt?
user2390246
Egal, ich glaube, ich habe meine eigene Frage beantwortet. Dies liegt an der Referenz zum Lookback in der folgenden Zeile.
user2390246
Ja, es ist, weil wir den Charakter vor der yVerwendung erfassen wollen$1
Kritixi Lithos
Ich glaube, ich habe es in 57 Bytes: Versuchen Sie es online
Business Cat
16

JavaScript (ES6),  109  97 Byte

s=>s[R='replace'](/([^aeiou])y$/,'$1ie')[R](/fe?$/,'ve')[R](/([^aeiou]o|[sxz]|[cs]h)$/,'$1e')+'s'

Probieren Sie es online!

Arnauld
quelle
Warum hast du einen ()vor fe?
Kodos Johnson
1
@KodosJohnson Alle replace()Iterationen enthalten einen Verweis auf die erste übereinstimmende Gruppe (mit $1). Deshalb brauche ich hier eine leere passende Gruppe.
Arnauld
Hast du es versucht (?<![aeiou])y?
Titus
@Titus Leider implementiert JS keine Lookbehind-Behauptungen.
Arnauld
11

Batch, 325 Bytes

@set/ps=
@for %%v in (a e i o u)do @(
for %%e in (o y)do @if %s:~-2%==%%v%%e goto s
if %s:~-2%==%%vf set s=%s:~,-1%ve&goto s
if %s:~-3%==%%vfe set s=%s:~,-2%ve&goto s
)
@if %s:~-1%==y set s=%s:~,-1%ie
@for %%e in (o s x z)do @if %s:~-1%==%%e set s=%s%e
@for %%e in (c s)do @if %s:~-2%==%%eh set s=%s%e
:s
@echo %s%s
Neil
quelle
Was ist mit @echo offam Anfang und nicht @überall? Auch @set/ps=scheint ein bisschen rostig von einem Telefon. Wird nicht die sVariable ohnehin die Slicing - Werte akzeptieren?
KeyWeeUsr
@KeyWeeUsr @echo offist bereits 9 Bytes ohne die Newline, also speichert es mich nichts. Wird auch @set/ps=benötigt, um den Wert zuerst einzugeben.
Neil
7

Haskell, 216 207 205 Bytes

Vielen Dank an @Lynn, @ user1472751 und @Laikoni für die Hilfe!

import Data.List
(!)s=or.map(\x->x`isSuffixOf`s)
c=['b'..'z']\\"eiou"
p s|s!(words"s x z ch sh"++map(:"o")c)=s++"es"|s!map(:"y")c=init s++"ies"|s!["f"]=init s++"ves"|s!["fe"]=(init.init)s++"ves"|0<1=s++"s"

Lesbar

import Data.List;

endsWithOneOf :: String -> [String] -> Bool
endsWithOneOf str ends = (or . map (\end -> end `isSuffixOf` str)) ends 

consonants :: [Char]
consonants = ['a'..'z'] \\ "aeiou"

pluralize :: String -> String
pluralize str
    | str `endsWithOneOf` (words "s x z ch sh" ++ (map (:"o") consonants)) = str ++ "es"
    | str `endsWithOneOf` (map (:"y") consonants) = init str ++ "ies"
    | str `endsWithOneOf` ["f"] = init str ++ "ves"
    | str `endsWithOneOf` ["fe"] = (init.init) str ++ "ves"
    | otherwise = str ++ "s"

Erläuterung

import Data.Listfür die Funktion isSuffixOf. endsWithOneOf( in der Golfversion) gibt zurück, ob eines der Listenelemente ein Ende der Zeichenfolge ist. consonants(c)ist nur eine Liste aller Konsonanten.

Schließlich pluralize(p)prüft die Endungen und kehrt die richtige Pluralisierung.

Beispiel:

p "potato" == "potatoes"
Eisfunke
quelle
1
Schöne lösung! Dies sind 216 Zeichen , die jedoch mehrere Bytes lang sind, sodass Ihre Lösung 226 Bytes umfasst. (Code-Golf-Herausforderungen werden explizit in Bytes gewertet, da Sie beim Zählen von Zeichen manchmal schummeln können.) Sie können es jedoch einfach in umbenennen !! Außerdem words"s x z ch sh"spart 5 Byte. Entfernen Sie die Parens (map(:"o")c))und (map(:"y")c))sparen Sie 4 weitere.
Lynn
Danke für die Hilfe, @Lynn! Ich habe Ihre Vorschläge umgesetzt.
Eisfunke
2
Sie können ein Byte speichern, indem Sie verwenden, c=['b'..'z']\\"eiou"da 'a'immer entfernt wird.
user1472751
1
0<1ist ein Byte kürzer als True. Auch Zeilenumbrüche haben die gleiche Byteanzahl wie ;, machen den Code jedoch ein bisschen besser lesbar.
Laikoni
5

Perl, 66 + 2 ( -plFlag) = 68 Bytes

$_.=/(ch|sh?|x|z|[^aeiou]o)$/+s/([^aeiou])y$/$1i/+s/fe?$/v/?es:"s"

Verwenden von:

perl -ple '$_.=/(ch|sh?|x|z|[^aeiou]o)$/+s/([^aeiou])y$/$1i/+s/fe?$/v/?es:"s"' <<< car

Probieren Sie es auf Ideone.

Denis Ibaev
quelle
5

Röda , 80 Bytes

f&s{s~="([^aeiou])y$","$1ie","([sxz]|[cs]h|[^aeiuo]o)$","$1e","fe?$","ve"s.="s"}

Die Funktion ändert ihr Argument. Verwendung: main word { f word; print word }Hier ist eine Version, die einen Rückgabewert (83 Bytes) verwendet:

f s{s~="([^aeiou])y$","$1ie","([sxz]|[cs]h|[^aeiuo]o)$","$1e","fe?$","ve";[s.."s"]}

Und ist eine Funktion , die unendlich viele Werte aus dem Eingangsstrom gelesen und schiebt Pluralformen mit dem Ausgangsstrom ( 87 83 Bytes):

{replace"([^aeiou])y$","$1ie","([sxz]|[cs]h|[^aeiuo]o)$","$1e","fe?$","ve","$","s"}

Es ist eine anonyme Funktion, da dies kürzer ist als das Erstellen einer benannten Funktion.

fergusq
quelle
Wie können Sie das Ergebnis der ersten Funktion anzeigen (die mit beginnt f&s)? f("word")
Scheint
@KritixiLithos Der Parameter ist eine Referenz, daher muss das Argument eine Variable sein.
Fergusq
5

PHP, 103 100 Bytes

<?=preg_replace(['/([^aeiou]o|sh?|x|z|ch)$/','/(?<![aeiou])y$/','/fe?$/'],['\1e',ie,ve],$argv[1]).s;

Probieren Sie es online!

Die preg_replaceFunktion nimmt eine Reihe von Mustern und Ersetzungen auf.

  • 2 Bytes gespart dank Titus.
  • Dank Dewi Morgan 1 Byte gespeichert.
Kodos Johnson
quelle
2
Ich denke, Sie können ein Byte mit -Rund speichern $argn. Und wenn Sie eine Behauptung mit ySave Two verwenden: (?<![aeiou])y$Ermöglicht ieals Ersatz: Nein \1, keine Anführungszeichen.
Titus
1
Ein weiteres Byte von([^aeiou]o|sh?|x|z|ch)$
Dewi Morgan
@Titus Tatsächlich sieht es so aus, als gäbe es eine 1-Byte-Strafe für die Verwendung -R(aber nicht -r), sodass sich die Byteanzahl leider nicht ändert. Aber der Lookbehind-Vorschlag funktioniert großartig. Vielen Dank.
Kodos Johnson
4

Python 3, 271 239 199 Bytes

Vielen Dank an @ovs für die Reduzierung um 72 Bytes!

lambda s,v="aeiou":(s[-2:]=="fe"and s[:-2]+"ve"or s[:-1]+((s[-1]=="y"and s[-2]not in v)*"ie"or s[-1]=="f"and"ve"or s[-1]+((s[-1]in"sxz"or s[-2:]in["ch","sh"])+(s[-1]=="o"and s[-2]not in v))*"e"))+"s"

Probieren Sie es online!

numbermaniac
quelle
1
Sie können unnötige Leerzeichen entfernen und das erste mit dem letzten kombinieren elif. Die einzelnen Zeichenlisten können durch Zeichenfolgen ersetzt werden. Das Umschalten auf Python spart zusätzliche 3 Bytes. tio
ovs
@ovs Fertig, danke! Ich habe das elifs aber nicht kombiniert , weil das heißt potatowird potaties.
Numbermaniac
1
Ich habe in die falsche Zeile geschaut;). Sie können das if mit dem letzten elif kombinieren. Um weitere Bytes zu sparen, ersetzen Sie die letzte Zeile durch print(s+"s")und entfernen Sie die Sonst-Groß- / Kleinschreibung bei jedem Anhängen an das Wort. Tio
ovs
1
Wenn Sie Ihre if / elif-Logik durch and/*und ersetzen or/+und eine unbenannte Lambda-Funktion erstellen, erhalten Sie sie unter 200 Byte (ich habe die Fälle ein wenig vertauscht)
ovs
@ovs Ooh, das print(s+"s")ist schlau. Alles hat sich geändert; Du hast so ziemlich alles umgeschrieben, lol. Vielen Dank! (Ich wusste nicht einmal, dass Sie so etwas tun können True and "string")
numbermaniac
2

sed, 70 79 bytes

69 78 + 1 für -E(BSD) / -r(GNU) -Flag

s/([^aeiou])y$/\1ie/
s/([^aeiou]o|[fxzs]|[sc]h)$/&e/
s/fe/ve/
s/$/s/

Direkter Port der Retina-Antwort .

Kevin
quelle
2

Pip , 63-61 Bytes

Y`[^aeiou]`OaR[C`sh?|x|z|ch`Cy.'y`fe?`y.'o].'$[_B.'i'v_].'e's

So nah daran, die Retina zu fangen! Aber es wird wahrscheinlich nicht passieren. :(

Probieren Sie es online!

Erläuterung

Grundlegende Strategie: Replace führt mehrere Ersetzungen nacheinander durch, wenn Listen mit Mustern und Ersetzungen angegeben werden. Wir möchten folgende Ersetzungen vornehmen:

  • (sh?|x|z|ch)$ -> füge ein e
  • [^aeiou]y-> ändere das yzu iund füge eine
  • fe?-> ändere vund füge eine
  • [^aeiou]o -> füge ein e

Dann wollen wir ein Unentschieden sangehen.

Tricks:

  • Der COperator, dem ein regulärer Ausdruck gegeben wurde, schließt ihn in eine Erfassungsgruppe ein. C`xyz`ist ein Byte kürzer als `(xyz)`.
  • Eine Liste von Regexen oder Ersetzungen, die alle mit demselben Zeichen enden, kann erstellt werden, indem das Zeichen mit der Liste verkettet wird, anstatt es in alle Elemente aufzunehmen. Das Verknüpfen eines Skalars (Strings) mit einem Muster (Regex / Ersetzung) wird zu einem Muster.
  • Anstatt das zu verketten s(und uns mit der Rangfolge von Rund zu befassen .), können wir einfach Oden Hauptteil des Wortes ausgeben und das dann sseparat drucken .

Code mit Leerzeichen und Kommentaren:

                  a is 1st cmdline input (implicit)
Y`[^aeiou]`       Yank the consonant regex into the y variable
O a R             Output (without newline): a, with the following replacements:
 [                List of regexes to replace:
  C `sh?|x|z|ch`    (sh?|x|z|ch)
  Cy . 'y           ([^aeiou])y
  `fe?`             fe?
  y . 'o            [^aeiou]o
 ] . '$           End of list; concatenate $ to each item
 [                List of replacements:
  _                 Identity function (replace with whole match)
  B                 B is short for {b}, a function returning its second argument; as a
                    callback function for regex replacement, the second argument is
                    the value of capturing group 1 (the consonant before y)
    . 'i            To that, concatenate i
  'v                Scalar literal v
  _                 Identity function
 ] . 'e           End of list; concatenate e to each item
's                Return Scalar literal s, which is autoprinted
DLosc
quelle
2

C # 73 163 Bytes:

Func<string,string>p=System.Data.Entity.Design.PluralizationServices.PluralizationService.CreateService(System.Globalization.CultureInfo.CurrentCulture).Pluralize

Ja, eine andere Sprache ist integriert (obwohl Sie einen Verweis hinzufügen müssen System.Data.Entity.Design.dll)

Benutzen:

var words = new[] { "car", "bus", "potato", "knife", "penny", "exception", "wolf", "eye", "decoy", "radio" };
foreach (var word in words)
{
    var plural = p(word);
    Console.Out.WriteLine($"{word} => {plural}");
}

Ausgabe:

car => cars
bus => buses
potato => potatoes
knife => knives
penny => pennies
exception => exceptions
wolf => wolves
eye => eyes
decoy => decoys
radio => radios
RoadieRich
quelle
Willkommen auf der Seite. Wie führe ich diesen Code aus?
Wheat Wizard
@ WheatWizard aktualisiert. Sollte ich mehr Details (unter Verwendung von Anweisungen usw.) in die Byteanzahl einbeziehen?
RoadieRich
Interessante Kleinigkeit, das Gegenteil davon (Singularize) scheitert an einigen einfachen Testfällen. Zum Beispiel ist es davon überzeugt, dass der Singular von "Kursen" "Kurse" ist.
Morgan Thrapp
Ich denke, die Namespaces müssen in die Byteanzahl dieses Benutzers einbezogen werden, insbesondere , da es nicht zu den "normalen" gehört. Aber ich denke, Sie müssen dies auch mindestens in ein Lambda einschließen und das Argument an die Methode übergeben. Da dies nur eine Methodengruppe ist
pinkfloydx33
@ pinkfloydx33 jetzt besser?
RoadieRich
2

Python 199 187 176 Bytes

lambda s:s+'\bve'*(s[-1]=='f')+'\b\bve'*(s[-2:]=='fe')+'e'*(s[-1]in'sxz'or s[-2:]in('ch','sh')or s[-1]=='o'and s[-2]not in'aiueo')+'\bie'*(s[-1]=='y'and s[-2]not in'aiueo')+'s'
Felipe Nardi Batista
quelle
2

Schienenläufer, 18 Bytes

$><<gets.pluralize

Beispiel:

$ echo knife | rails r filename.rb
knives
SztupY
quelle
Das ist eine esoterische Sprache.
Ven
1

Python, 296 Bytes

z = input()
if z[-1]in['s','x','z','ch','sh']:print(z+'es')
elif z[-1]=='y'and z[-2]not in['a','e','i','o','u']:print(z[:-1]+'ies')
elif z[-2:]=='fe':print(z[:-2]+'ves')
elif z[-1]=='f':print(z[:-1]+'ves')
elif z[-1]=='o'and z[-2]not in['a','e','i','o','u']:print(z[:-1]+'oes')
else:print(z+'s')
just_floating
quelle
0

Direkter Hafen von Retina:

Ruby , 111 Bytes

'sub(/([^aeiou])y/){"#{$1}ie"};sub(/(.*)([^aeiou]o|[fxzs]|[sc]h)$/){"#{$1}#{$2}e"};sub(/fe/,"ve");sub(/$/,"s")'

Probieren Sie es online!

Rufen Sie via auf ruby -lpeund geben Sie eine Datei wie input.txtbeim ersten CLI-Argument an.

stephanmg
quelle
Kann wahrscheinlich mehr "Golf" sein. Btw .: Kann man Dateien zu TIO hinzufügen?
stephanmg
0

C 321 Bytes

#define E else if(
#define C unsigned char
C*p(C*b){static C r[999],i,w,n,m;for(n=w=i=0;r[i]=b[i];n=w,w=b[i++]);m=!strchr("aeiou",n);if(strchr("sxz",w)||(w=='h'&&strchr("cs",n))||(w=='o'&&m))r[i++]='e';E'y'==w&&m)r[i-1]='i',r[i++]='e';E'f'==w)r[i-1]='v',r[i++]='e';E'f'==n&&w=='e')r[i-2]='v';r[i++]='s';r[i]=0;return r;}

Prüfung:

C*mx[]={"car","bus","potato","knife","penny","exception","wolf","eye","decoy","radio",0};

main()
{unsigned i;
 for(i=0;mx[i];++i)
    printf("[%s] [%s]\n", mx[i], p(mx[i]));
 return 0;
}

Ergebnisse:

[car] [cars]
[bus] [buses]
[potato] [potatoes]
[knife] [knives]
[penny] [pennies]
[exception] [exceptions]
[wolf] [wolves]
[eye] [eyes]
[decoy] [decoys]
[radio] [radios]
[radio] [radios]
RosLuP
quelle
Es sollte wolvesnicht sein wolfves.
mbomb007
@ceilingcat was ist mit "statischem Cr [256], / * Z =" aeiou ", i = 0, w, n;" anstelle von "statisch C r [256]; C / * Z =" aeiou ", i = 0, w, n;"
RosLuP vor
268 bytes
ceilingcat vor
-1

Java 7, 408 Bytes

Golf gespielt:

boolean b="bcdfghjklmnpqrstvwxyzs".contains(String.valueOf(s.charAt(s.length()-2))); String x=s.substring(0,s.length()-1);if(s.endsWith("s")||s.endsWith("x")||s.endsWith("z")||s.endsWith("ch")||s.endsWith("sh"))return s+"es";if(s.endsWith("y")&&b)return x+"ies";if(s.endsWith("f")) return x+"ves";if(s.endsWith("fe"))return s.substring(0,s.length()-2)+"ves";if(s.endsWith("o")&&b)return s+"es";return s+="s";

Grundsätzlich wird getestet, wie das Ende der Zeichenfolge lautet, und Buchstaben werden hinzugefügt / ersetzt, je nachdem, in welchem ​​Fall dies der Fall ist. Der Boolesche Wert und der String am Anfang dienen nur dazu, Wiederholungen in den Testfällen zu entfernen und den Code zu verkleinern.

Lesbare Version:

public static String pluralize(String s){

// Consonant at the 2nd last position?
boolean b = "bcdfghjklmnpqrstvwxyzs".contains(String.valueOf(s.charAt(s.length()-2))); 

// Substring for cases where last letter needs to be replaced
String x = s.substring(0,s.length()-1);

if(s.endsWith("s") || s.endsWith("x") || s.endsWith("z") || s.endsWith("ch") || s.endsWith("sh"))
    return s + "es";
if(s.endsWith("y") && b)
    return x + "ies";
if(s.endsWith("f")) 
    return x + "ves";
if(s.endsWith("fe"))
    return s.substring(0,s.length()-2) + "ves";
if(s.endsWith("o") && b)
    return s + "es";

return s += "s";
}
Nick
quelle
6
Sie können kein Snippet verwenden.
Okx
-1

Java

public static String pluralize(final String singularNoun) {
    switch (singularNoun) {
        case "man":
            return "men";
        case "woman":
            return "women";
        case "child":
            return "children";
        case "foot":
            return "feet";
        case "tooth":
            return "teeth";
        case "mouse":
            return "mice";
        case "person":
            return "people";
        case "sheep":
        case "deer":
        case "fish":
        case "series":
        case "species":
            // no change
            return singularNoun;
        case "roof":
        case "cliff":
        case "piano":
        case "photo":
            // break this switch and just add s;
            break;
        default:
            final int lastIndex = singularNoun.length() - 1;
            final String last2Chars = singularNoun.substring(lastIndex - 1);
            final char firstChar = last2Chars.charAt(0);
            final char secondChar = last2Chars.charAt(1);

            switch (last2Chars) {
                case "ch":
                case "sh":
                    return singularNoun + "es";
                case "fe": // life => lives, knife => knives
                    return singularNoun.substring(0, lastIndex - 1) + "ves";
                default:
                    switch (secondChar) {
                        case 's':
                        case 'x':
                        case 'z':
                            return singularNoun + "es";
                        case 'f':
                            return singularNoun.substring(0, lastIndex - 1) + "ves";
                        case 'y':
                            if (!isVowel(firstChar)) {
                                return singularNoun.substring(0, lastIndex) + "ies";
                            }
                        case 'o':
                            if (!isVowel(firstChar)) {
                                return singularNoun + "es";
                            }
                    }
            }
    }

    return singularNoun + "s";
}
maohieng
quelle
3
Während dies den Algorithmus korrekt implementiert, macht es absolut keinen Versuch, Golf zu spielen, und ist größtenteils vollständig redundanter Code. Ich glaube auch nicht, dass dies isVoweleine native Funktion ist
Jo King,
1
Ich denke auch, dass isVowelim Code angezeigt werden sollte, sieht nicht nach einem eingebauten aus.
stephanmg